JDK-8141330 : [JVMCI] avoid deadlock between application thread and JVMCI compiler thread under -Xbatch
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-11-03
  • Updated: 2016-01-08
  • Resolved: 2015-11-18
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 9
9 b96Fixed
Related Reports
Relates :  
Description
It's possible for deadlock to occur when an app thread holds a lock and then schedules a blocking compilation where the JVMCI compiler thread then tries to acquire the lock:

"JVMCI CompilerThread7" #12 daemon prio=9 os_prio=0 tid=0x00007f69540e7000 nid=0x45c0 waiting for monitor entry [0x00007f613897a000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at java.util.Hashtable.get(Hashtable.java:362)
	- waiting to lock <0x00007f6140051ae0> (a java.util.Hashtable)
	at java.net.URL.getURLStreamHandler(URL.java:1128)
	at java.net.URL.<init>(URL.java:592)
	at java.net.URL.<init>(URL.java:483)
	at java.net.URL.<init>(URL.java:432)
	at sun.security.provider.NativePRNG.getEgdUrl(NativePRNG.java:109)
	at sun.security.provider.NativePRNG.access$000(NativePRNG.java:74)
	at sun.security.provider.NativePRNG$1.run(NativePRNG.java:140)
	at sun.security.provider.NativePRNG$1.run(NativePRNG.java:128)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.security.provider.NativePRNG.initIO(NativePRNG.java:127)
	at sun.security.provider.NativePRNG.<clinit>(NativePRNG.java:91)
	at sun.security.provider.SunEntries.putEntries(SunEntries.java:96)
	at sun.security.provider.Sun.<init>(Sun.java:56)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at java.lang.Class.newInstance(Class.java:442)
	at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:221)
	at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:206)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.security.jca.ProviderConfig.doLoadProvider(ProviderConfig.java:206)
	at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:187)
	- locked <0x00007f61470cf4d0> (a sun.security.jca.ProviderConfig)
	at sun.security.jca.ProviderList.getProvider(ProviderList.java:233)
	at sun.security.jca.ProviderList.getService(ProviderList.java:331)
	at sun.security.jca.GetInstance.getInstance(GetInstance.java:157)
	at java.security.cert.CertificateFactory.getInstance(CertificateFactory.java:183)
	at sun.security.pkcs.PKCS7.parseSignedData(PKCS7.java:300)
	at sun.security.pkcs.PKCS7.parse(PKCS7.java:186)
	at sun.security.pkcs.PKCS7.parse(PKCS7.java:154)
	at sun.security.pkcs.PKCS7.<init>(PKCS7.java:136)
	at sun.security.util.SignatureFileVerifier.<init>(SignatureFileVerifier.java:95)
	at java.util.jar.JarVerifier.processEntry(JarVerifier.java:297)
	at java.util.jar.JarVerifier.update(JarVerifier.java:228)
	at java.util.jar.JarFile.initializeVerifier(JarFile.java:383)
	at java.util.jar.JarFile.getInputStream(JarFile.java:450)
	- locked <0x00007f6147021310> (a java.util.jar.JarFile)
	at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:940)
	at sun.misc.Resource.cachedInputStream(Resource.java:77)
	- locked <0x00007f6147022fb8> (a sun.misc.URLClassPath$JarLoader$2)
	at sun.misc.Resource.getByteBuffer(Resource.java:160)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:454)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	- locked <0x00007f6147020da0> (a java.lang.Object)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
	- locked <0x00007f6147020cd0> (a java.lang.Object)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at com.oracle.graal.graphbuilderconf.MethodSubstitutionPlugin.resolveClass(MethodSubstitutionPlugin.java:172)
	at com.oracle.graal.hotspot.meta.HotSpotGraphBuilderPlugins.registerAESPlugins(HotSpotGraphBuilderPlugins.java:296)
	at com.oracle.graal.hotspot.meta.HotSpotGraphBuilderPlugins.create(HotSpotGraphBuilderPlugins.java:124)
	at com.oracle.graal.hotspot.amd64.AMD64HotSpotBackendFactory.createGraphBuilderPlugins(AMD64HotSpotBackendFactory.java:141)
	at com.oracle.graal.hotspot.amd64.AMD64HotSpotBackendFactory.createBackend(AMD64HotSpotBackendFactory.java:125)
	at com.oracle.graal.hotspot.HotSpotGraalRuntime.<init>(HotSpotGraalRuntime.java:109)
	at com.oracle.graal.hotspot.HotSpotGraalCompilerFactory.createCompiler(HotSpotGraalCompilerFactory.java:75)
	at com.oracle.graal.hotspot.HotSpotGraalCompilerFactory.createCompiler(HotSpotGraalCompilerFactory.java:38)
	at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.getCompiler(HotSpotJVMCIRuntime.java:184)
	- locked <0x00007f614392d850> (a jdk.vm.ci.hotspot.HotSpotJVMCIRuntime)
	at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.compileMethod(HotSpotJVMCIRuntime.java:228)

"main" #1 prio=5 os_prio=0 tid=0x00007f695400a000 nid=0x45b4 waiting on condition [0x00007f695b97e000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.String.equals(String.java:965)
	at java.util.Hashtable.get(Hashtable.java:366)
	- locked <0x00007f6140051ae0> (a java.util.Hashtable)
	at java.net.URL.getURLStreamHandler(URL.java:1128)
	at java.net.URL.<init>(URL.java:413)
	at java.net.URL.<init>(URL.java:303)
	at java.net.URL.<init>(URL.java:326)
	at java.io.File.toURL(File.java:686)
	at org.dacapo.harness.DacapoClassLoader.getJars(DacapoClassLoader.java:105)
	at org.dacapo.harness.DacapoClassLoader.create(DacapoClassLoader.java:46)
	at org.dacapo.harness.Benchmark.initialize(Benchmark.java:212)
	at org.dacapo.harness.Benchmark.<init>(Benchmark.java:184)
	at org.dacapo.harness.Benchmark.<init>(Benchmark.java:194)
	at org.dacapo.harness.Pmd.<init>(Pmd.java:31)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at org.dacapo.harness.TestHarness.runBenchmark(TestHarness.java:211)
	at org.dacapo.harness.TestHarness.main(TestHarness.java:171)
	at Harness.main(Harness.java:17)

To avoid this, we need to add a timeout to the wait performed by the app thread (i.e. in CompileBroker::wait_for_completion). The trickiest part is deciding which thread frees the CompileTask.
Comments
[11/11/15, 8:12:59 AM] Chris Thalinger: Is there a test that triggers this deadlock? [11/11/15, 8:14:00 AM] Doug Simon: it used to be triggered by running dacapo pmd with -Xbatch
11-11-2015

The potential for deadlock will always be there for any VM subsystem that executes Java code in non-app threads. However, in this particular case, the proposed solution should be fine since we're only talking about -Xbatch which is primarily (only?) used by VM compiler engineers to force more compilation for testing purposes. We do not currently eagerly initialize the JVMCI system at VM startup. Doing so negatively impacts startup time. Maybe an AOT system would help with this. We've seen a deadlock between a JVMCI compiler thread and the main thread during VM startup. The JVMCI thread was doing some ServiceLoader work and the main thread was still in LauncherHelper.checkAndLoadMain. This looks like a potential bug in the JDK's ServiceLoader mechanism - see JDK-8139709. Note that no app classes will be loaded by a JVMCI compiler thread since JVMCI compilers only look at already loaded code.
04-11-2015

Classloading in the compiler threads, in response to a compilation request will be fraught with deadlock potentials. I would have expected some aggressive pre-loading of things needed by the JVMCI system to avoid this kind of situation. Timing out the blocking of the app thread is a way to ameliorate the problem when it occurs, but steps should still be taken to avoid the deadlock potential.
04-11-2015

https://lafo.ssw.uni-linz.ac.at/hg/openjdk-jvmci-9/hotspot/rev/b0976868f2fa
03-11-2015