JDK-8214287 : SpecJbb2005StressModule got uncaught exception
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jfr
  • Affected Version: 12
  • Priority: P1
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-11-26
  • Updated: 2019-07-02
  • Resolved: 2018-11-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12
11.0.5-oracleFixed 12 b22Fixed
Related Reports
Relates :  
Description
The fix for JDK-8214161 wasn't complete. There are still failures in Kitchensink testing.

[glue.process.err] [stress.process.err] --------------------------------------------------------------------------------
[glue.process.err] [stress.process.err] SpecJbb2005StressModule got uncaught exception in init at Fri Nov 23 05:54:47 PST 2018 (1542981287337)
[glue.process.err] [stress.process.err] java.lang.IllegalAccessError: class jdk.internal.event.X509CertificateEvent (in module java.base) cannot access class jdk.jfr.internal.handlers.EventHandler (in module jdk.jfr) because module java.base does not read module jdk.jfr
[glue.process.err] [stress.process.err] 	at java.base/jdk.internal.event.X509CertificateEvent.shouldCommit(X509CertificateEvent.java)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.provider.X509Factory.commitEvent(X509Factory.java:773)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:108)
[glue.process.err] [stress.process.err] 	at java.base/java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:355)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.parseSignedData(PKCS7.java:328)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.parse(PKCS7.java:186)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.parse(PKCS7.java:154)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.<init>(PKCS7.java:136)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.util.SignatureFileVerifier.<init>(SignatureFileVerifier.java:127)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:297)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:230)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:758)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarFile.getInputStream(JarFile.java:839)
[glue.process.err] [stress.process.err] 	at java.base/sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:167)
[glue.process.err] [stress.process.err] 	at java.base/java.net.URLClassLoader.getResourceAsStream(URLClassLoader.java:293)
[glue.process.err] [stress.process.err] 	at applications.kitchensink.utils.Specjbb2005ClassLoader.loadClass(Specjbb2005ClassLoader.java:183)
[glue.process.err] [stress.process.err] 	at applications.kitchensink.process.stress.modules.SpecJbb2005StressModule.init(SpecJbb2005StressModule.java:111)
[glue.process.err] [stress.process.err] 	at applications.kitchensink.process.stress.modules.StressModule.run(StressModule.java:48)
[glue.process.err] [stress.process.err] --------------------------------------------------------------------------------
[glue.process.err] [stress.process.err] --------------------------------------------------------------------------------
[glue.process.err] [stress.process.err] SpecJvm2008DerbyStressModule got uncaught exception in execute at Fri Nov 23 05:54:47 PST 2018 (1542981287458)
[glue.process.err] [stress.process.err] java.lang.IllegalAccessError: class jdk.internal.event.X509CertificateEvent (in module java.base) cannot access class jdk.jfr.internal.handlers.EventHandler (in module jdk.jfr) because module java.base does not read module jdk.jfr
[glue.process.err] [stress.process.err] 	at java.base/jdk.internal.event.X509CertificateEvent.shouldCommit(X509CertificateEvent.java)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.provider.X509Factory.commitEvent(X509Factory.java:773)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:108)
[glue.process.err] [stress.process.err] 	at java.base/java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:355)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.parseSignedData(PKCS7.java:328)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.parse(PKCS7.java:186)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.parse(PKCS7.java:154)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.pkcs.PKCS7.<init>(PKCS7.java:136)
[glue.process.err] [stress.process.err] 	at java.base/sun.security.util.SignatureFileVerifier.<init>(SignatureFileVerifier.java:127)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:297)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:230)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:758)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JarFile.ensureInitialization(JarFile.java:1035)
[glue.process.err] [stress.process.err] 	at java.base/java.util.jar.JavaUtilJarAccessImpl.ensureInitialization(JavaUtilJarAccessImpl.java:69)
[glue.process.err] [stress.process.err] 	at java.base/jdk.internal.loader.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:870)
[glue.process.err] [stress.process.err] 	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:482)
[glue.process.err] [stress.process.err] 	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:423)
[glue.process.err] [stress.process.err] 	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:417)
[glue.process.err] [stress.process.err] 	at java.base/java.security.AccessController.doPrivileged(AccessController.java:688)
[glue.process.err] [stress.process.err] 	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:416)
[glue.process.err] [stress.process.err] 	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
[glue.process.err] [stress.process.err] 	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
[glue.process.err] [stress.process.err] 	at applications.kitchensink.utils.GetOutUpdatingClassLoader.loadClass(GetOutUpdatingClassLoader.java:85)
[glue.process.err] [stress.process.err] 	at applications.kitchensink.process.stress.modules.SpecJvm2008StressModule.execute(SpecJvm2008StressModule.java:187)
[glue.process.err] [stress.process.err] 	at applications.kitchensink.process.stress.modules.StressModule.run(StressModule.java:66)
[glue.process.err] [stress.process.err] --------------------------------------------------------------------------------

Comments
Fix Request (11u): Request to backport this fix for Oracle 11.0.5 parity. Patch applies cleanly with minor fuzz. Will be tested at SAP before pushing.
22-06-2019

On the topic of 2, we can probably avoid changing anything here if we add in 1 and 3 - thx.
26-11-2018

public boolean shouldCommit(); descriptor: ()Z flags: (0x1001) ACC_PUBLIC, ACC_SYNTHETIC Code: stack=3, locals=1, args_size=1 0: getstatic #52 // Field eventHandler:Ljdk/jfr/internal/handlers/EventHandler; 3: ifnull 21 6: getstatic #52 // Field eventHandler:Ljdk/jfr/internal/handlers/EventHandler; 9: aload_0 10: getfield #42 // Field duration:J 13: invokevirtual #80 // Method jdk/jfr/internal/handlers/EventHandler.shouldCommit:(J)Z 16: ifeq 21 19: iconst_1 20: ireturn 21: iconst_0 22: ireturn StackMapTable: number_of_entries = 1 frame_type = 21 /* same */
26-11-2018

Nice analysis Markus. 1. Sounds like a no brainer. 2. The eager flag should be enabled when the FlightRecorderListener#initialized is being called. Do we really need to change behaviour here? 3. It would be nice if we could avoid this as durational events are likely to be added in the future. I think in an early prototype, isEnabled() was called from shouldCommit(), but was removed to reduce if checks. Maybe we need to add it back, or at least the null check?
26-11-2018

I will modify shouldCommit() to do the null check as well - thanks. As shouldCommit() already inspect the enabled setting in the handler as part of the conjunction, invoking isEnabled() would then evaluate enabled in the handler twice. There is an existing fail label in shouldCommit to drop to in the situation of a guardHandlerReference that i can use.
26-11-2018

JDK-8214161 ensured the eventhandler field of the event was untyped if the jdk.jfr module was not available, changing the type of the static field, from: public final class jdk.internal.event.X509CertificateEvent extends jdk.internal.event.Event ... private static jdk.jfr.internal.handlers.EventHandler eventHandler; descriptor: Ljdk/jfr/internal/handlers/EventHandler; flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC to: public final class jdk.internal.event.X509CertificateEvent extends jdk.internal.event.Event ... private static java.lang.Object eventHandler; descriptor: Ljava/lang/Object; flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC After JDK-8214161, the class had no references to types located in jdk.jfr. Except in this situation: When JFR bootstraps, it will load a set of well-known classes for instrumentation. To avoid using retransform during bootstrap for this set, we have a fast path to insert all instrumentation code upon initial load. This is accomplished by setting a flag in the VM to perform "eager" instrumentation. Under this flag, there is an upcall to Java for immediate instrumentation, compared to only the schema adjustments performed in native. Now, if an event in java.base is loaded during the JFR bootstrap window, it will also upcall for eager instrumentation (takes same path) This will result in the event code eventually looking something like this: .. public boolean isEnabled(); descriptor: ()Z flags: (0x1001) ACC_PUBLIC, ACC_SYNTHETIC Code: stack=1, locals=1, args_size=1 0: getstatic #52 // Field eventHandler:Ljdk/jfr/internal/handlers/EventHandler; 3: ifnull 13 6: getstatic #52 // Field eventHandler:Ljdk/jfr/internal/handlers/EventHandler; 9: invokevirtual #77 // Method jdk/jfr/internal/handlers/EventHandler.isEnabled:()Z 12: ireturn 13: iconst_0 14: ireturn StackMapTable: number_of_entries = 1 frame_type = 13 /* same */ public boolean shouldCommit(); descriptor: ()Z flags: (0x1001) ACC_PUBLIC, ACC_SYNTHETIC Code: stack=3, locals=1, args_size=1 0: getstatic #52 // Field eventHandler:Ljdk/jfr/internal/handlers/EventHandler; 3: aload_0 4: getfield #42 // Field duration:J 7: invokevirtual #80 // Method jdk/jfr/internal/handlers/EventHandler.shouldCommit:(J)Z 10: ifeq 15 13: iconst_1 14: ireturn 15: iconst_0 16: ireturn StackMapTable: number_of_entries = 1 frame_type = 15 /* same */ So now the handler field is again typed, for eventHandler:Ljdk/jfr/internal/handlers/EventHandler. This is not a problem if the events being loaded are ���regular events��� because they will call FlightRecorder.register(class) as part of their <clinit>, where one part will take care of module graph edges / exports to ensure the visibility / reachability of involved types. But for events located in java.base this now becomes a problem, because they are excluded from calling FlightRecorder.register() as part of <clinit>. The reason is again the module graph inversion. Instead the JFR engine will need to pull in these classes as a step in the bootstrap process (and for our situation here, that step has not yet been reached when this problem occurs). The java.base code calls event.shouldCommit() which will attempt to load the event handler. To make matters even more complicated, even if we ensure type visibility, the existing code in java.base calling shouldCommit() will get an NPE. This is because the eventHandler field has not been installed yet (we have not reached that point yet in bootstrap). isEnabled() covers this situation, where it has inserted an ifnull instruction for the eventHandler field access (see above), but we currently don���t do the same for shouldCommit(). To fix this I suggest: 1. Let���s setup the java.base to jdk.jfr module read edge and export the relevant packages from jdk.jfr to java.base unconditionally as part of the earliest JFR code to load (implies jdk.jfr is now available). This will ensure the graph is in place before any typed instrumentation occurs. 2. We can narrow the window of time that the "eager" instrumentation is open during JFR bootstrap. Currently it is open during the entire native bootstrap phase. 3. Since the existing events in java.base are instant events, for these, shouldCommit() can be replaced by isEnabled(). isEnabled() includes a guard against dereferencing an eventHandler field that is null.
26-11-2018