Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-3420

Missing class unload events over JDI with Java 17

Linking RHIVOS CVEs to...Migration: Automation ...SWIFT: POC ConversionSync from "Extern...XMLWordPrintable

    • None
    • None
    • rhel-sst-java
    • None
    • False
    • False
    • Hide

      None

      Show
      None
    • None
    • None
    • None
    • None
    • If docs needed, set a value
    • None
    • 57,005

      Description of problem:

      We are evaluating OpenJDK 17 early access builds for a part of our product. We see missing class unload events received by Eclipse over JDI, when running a dedicated test to ensure class unload events are sent and received. Upon investigation, we can reproduce with a plain Java snippet and jdb. The problem is also seen with OpenJDK 16, but not with OpenJDK 15 (or, OpenJDK 11 and OpenJDK 8).

      Version-Release number of selected component (if applicable):

      OpenJDK 16
      OpenJDK 17

      Steps to Reproduce:

      First, I've made a change to OpenJDK code to check whether all class unload events are being sent (in case the Eclipse JDI implementation broke for some reason with OpenJDK 17). Its a printf in eventHandler.c :

      1. Apply the following patch on top of either OpenJDK 16 or OpenJDK 17 source code (e.g. from https://github.com/openjdk/jdk17.git) and compile the JDK (this allows seeing which class unload events will be sent over JDI):

      diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c b/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c
      index 2a5912f0777..19a91126e18 100644
      — a/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c
      +++ b/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c
      @@ -500,6 +500,7 @@ synthesizeUnloadEvent(void *signatureVoid, void *envVoid)
      char *durableSignature = jvmtiAllocate((int)strlen(signature)+1);
      (void)strcpy(durableSignature, signature);

      + printf("Sending class unload event for: %s\n", durableSignature);
      eventHelper_recordClassUnload(node->handlerID,
      durableSignature,
      eventBag);

      2. Place the following Java snippet in some folder:

      import java.io.File;
      import java.net.URL;
      import java.net.URLClassLoader;

      public class TestClassUnloadEvents {

      public static void main(String[] args) throws Exception

      { new TestClassUnloadEvents().execute(); }

      private URLClassLoader urlClassLoader;

      public void execute() throws Exception

      { beforeClassLoading(); loadClasses(); afterClassLoading(); unloadClasses(); afterClassUnloading(); }

      private void loadClasses() throws Exception {
      int numberOfClassesToLoad = Integer.valueOf("10");
      String libraryPath = "classes.jar";
      URL[] urls =

      { new File(libraryPath).toURI().toURL() }

      ;
      urlClassLoader = new URLClassLoader(urls, null);
      for (int i = 0; i < numberOfClassesToLoad; ++i)

      { String className = "sample.C" + i; Class<?> loadClass = urlClassLoader.loadClass(className); loadClass.newInstance(); }

      }

      private void unloadClasses() throws Exception

      { urlClassLoader.close(); urlClassLoader = null; System.gc(); System.runFinalization(); }

      public static void beforeClassLoading()

      { System.out.println("BEFORE CLASS LOADING"); }

      public static void afterClassLoading()

      { System.out.println("AFTER CLASS LOADING"); }

      public static void afterClassUnloading()

      { System.out.println("AFTER CLASS UNLOADING"); }

      }

      3. Place the attached "classes.jar" jar file in the same folder as the snippet.
      4. From that folder run the snippet. E.g.:
      /data/git/jdk17/build/linux-x86_64-server-release/jdk/bin/java -Xlog:class+load,class+unload -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8080 TestClassUnloadEvents.java
      5. Attach jdb with:
      /data/git/jdk17/build/linux-x86_64-server-release/jdk/bin/jdb -attach 8080
      6. Input "resume" for JDB, to let the application finish.
      7. Repeat the previous steps, observe that some prints (if not all) for class unloads are often missing.

      Actual results:

      Example output that I (often) see, which is unexpected:

      ...
      AFTER CLASS LOADING
      [4.863s][info][class,load] java.io.RandomAccessFile$1 source: /data/git/jdk17/build/linux-x86_64-server-release/jdk/modules/java.base
      [4.867s][info][class,unload] unloading class sample.C9 0x00000008001c5c30
      [4.867s][info][class,unload] unloading class sample.C8 0x00000008001c5a28
      [4.867s][info][class,unload] unloading class sample.C7 0x00000008001c5820
      [4.867s][info][class,unload] unloading class sample.C6 0x00000008001c5618
      [4.867s][info][class,unload] unloading class sample.C5 0x00000008001c5410
      [4.867s][info][class,unload] unloading class sample.C4 0x00000008001c5208
      [4.867s][info][class,unload] unloading class sample.C3 0x00000008001c5000
      [4.867s][info][class,unload] unloading class sample.C2 0x00000008001c4c10
      [4.867s][info][class,unload] unloading class sample.C1 0x00000008001c4a08
      [4.867s][info][class,unload] unloading class sample.C0 0x00000008001c4800
      [4.876s][info][class,load ] java.lang.ref.Finalizer$2 source: /data/git/jdk17/build/linux-x86_64-server-release/jdk/modules/java.base
      Sending class unload event for: Lsample/C9;
      Sending class unload event for: Lsample/C7;
      Sending class unload event for: Lsample/C5;
      Sending class unload event for: Lsample/C3;
      [4.876s][info][class,load ] java.lang.ref.Finalizer$1 source: /data/git/jdk17/build/linux-x86_64-server-release/jdk/modules/java.base
      AFTER CLASS UNLOADING
      ...

      Expected results:

      Expected output that I sometimes see (with Java 11 I always see all expected prints from the change, where event order is not relevant):

      ...
      AFTER CLASS LOADING
      [6.312s][info][class,load] java.io.RandomAccessFile$1 source: /data/git/jdk17/build/linux-x86_64-server-release/jdk/modules/java.base
      [6.315s][info][class,unload] unloading class sample.C9 0x00000008001c5c30
      [6.315s][info][class,unload] unloading class sample.C8 0x00000008001c5a28
      [6.315s][info][class,unload] unloading class sample.C7 0x00000008001c5820
      [6.315s][info][class,unload] unloading class sample.C6 0x00000008001c5618
      [6.315s][info][class,unload] unloading class sample.C5 0x00000008001c5410
      [6.315s][info][class,unload] unloading class sample.C4 0x00000008001c5208
      [6.315s][info][class,unload] unloading class sample.C3 0x00000008001c5000
      [6.315s][info][class,unload] unloading class sample.C2 0x00000008001c4c10
      [6.315s][info][class,unload] unloading class sample.C1 0x00000008001c4a08
      [6.315s][info][class,unload] unloading class sample.C0 0x00000008001c4800
      [6.325s][info][class,load ] java.lang.ref.Finalizer$2 source: /data/git/jdk17/build/linux-x86_64-server-release/jdk/modules/java.base
      Sending class unload event for: Lsample/C9;
      Sending class unload event for: Lsample/C7;
      Sending class unload event for: Lsample/C5;
      Sending class unload event for: Lsample/C3;
      Sending class unload event for: Lsample/C1;
      Sending class unload event for: Lsample/C0;
      Sending class unload event for: Lsample/C8;
      Sending class unload event for: Lsample/C6;
      Sending class unload event for: Lsample/C4;
      Sending class unload event for: Lsample/C2;
      [6.325s][info][class,load ] java.lang.ref.Finalizer$1 source: /data/git/jdk17/build/linux-x86_64-server-release/jdk/modules/java.base
      AFTER CLASS UNLOADING
      ...

      Additional info:

      Using our test, I've bisected the bug to those 2 commits:

      commit ba721f5f2fbbf08e22a9993dce0087f46b1f5552 (HEAD -> bad)
      Author: Coleen Phillimore <coleenp@openjdk.org>
      Date: Thu Nov 19 14:30:02 2020 +0000

      8212879: Make JVMTI TagMap table concurrent

      Co-authored-by: Kim Barrett <kbarrett@openjdk.org>
      Co-authored-by: Coleen Phillimore <coleenp@openjdk.org>
      Reviewed-by: stefank, ihse, zgu, eosterlund, sspitsyn, kbarrett

      commit 3a4b90f0863571dd372af6afab71862f3946a78f (good)
      Author: Sean Mullan <mullan@openjdk.org>
      Date: Thu Nov 19 14:15:57 2020 +0000

      8202343: Disable TLS 1.0 and 1.1

      Reviewed-by: xuelei, dfuchs, coffeys

      With HEAD at 3a4b90f0863571dd372af6afab71862f3946a78f, the problem is not seen. With HEAD at ba721f5f2fbbf08e22a9993dce0087f46b1f5552, the problem is seen. So I assume the cause is:

      https://github.com/openjdk/jdk17/commit/ba721f5f2fbbf08e22a9993dce0087f46b1f5552

              rhn-engineering-adinn Andrew Dinn
              jira-bugzilla-migration RH Bugzilla Integration
              Andrew Dinn Andrew Dinn
              David Kutalek David Kutalek
              Votes:
              0 Vote for this issue
              Watchers:
              8 Start watching this issue

                Created:
                Updated:
                Resolved: