JDK-7146776 : Deadlock between URLStreamHandler.getHostAddress and file.Handler.openconnection
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6u29,8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86
  • Submitted: 2012-02-17
  • Updated: 2022-01-19
  • Resolved: 2021-01-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 11 JDK 13 JDK 15 JDK 16 JDK 17 JDK 8 Other
11.0.11-oracleFixed 13.0.6Fixed 15.0.4Fixed 16.0.1Fixed 17 b06Fixed 8u291Fixed openjdk8u312Fixed
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-10M3527)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02-402, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
all OSs


A DESCRIPTION OF THE PROBLEM :
I've included the relevant deadlock stack trace below, but the root cause is that both

java.net.URLStreamHandler.getHostAddress

and

sun.net.www.protocol.file.Handler.openconnection

are synchronized. Either remove synchronized from getHostAddress and use a local lock object to protect that api or look at Handler and determine if you even need that to be synchronized or not (I didn't see any obvious reason it needed to be).


"dbwriter for ws_attachments [Run1User1Cycle] writing 1 objects, started batch at Thu Feb 16 13:06:00 MST 2012" prio=5 tid=7fed77863800 nid=0x118a61000 waiting for monitor entry [118a5e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at java.net.URLStreamHandler.getHostAddress(URLStreamHandler.java:412)
	- waiting to lock <7e002da38> (a sun.net.www.protocol.file.Handler)
	at java.net.URLStreamHandler.hostsEqual(URLStreamHandler.java:439)
	at sun.net.www.protocol.file.Handler.hostsEqual(Handler.java:117)
	at java.net.URLStreamHandler.sameFile(URLStreamHandler.java:396)
	at java.net.URLStreamHandler.equals(URLStreamHandler.java:316)
	at java.net.URL.equals(URL.java:842)
	at java.security.CodeSource.equals(CodeSource.java:135)
	at java.util.HashMap.get(HashMap.java:305)
	at java.security.SecureClassLoader.getProtectionDomain(SecureClassLoader.java:233)
	- locked <7e0040648> (a java.util.HashMap)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	- locked <7e00205b8> (a sun.misc.Launcher$AppClassLoader)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	- locked <7e00205b8> (a sun.misc.Launcher$AppClassLoader)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:295)
	- locked <7e04223c0> (a com.itko.lisa.test.TestExecClassLoader)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.loadClass(PersistenceUnitProcessor.java:261)


"ws_attachments [Run1User1Cycle]/0" daemon prio=5 tid=7fed7a80f000 nid=0x116172000 waiting for monitor entry [116170000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:293)
	- waiting to lock <7e00205b8> (a sun.misc.Launcher$AppClassLoader)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	at java.net.URL.getURLStreamHandler(URL.java:1144)
	at java.net.URL.<init>(URL.java:393)
	at java.net.URL.<init>(URL.java:283)
	at java.net.URL.<init>(URL.java:306)
	at sun.net.www.protocol.file.Handler.openConnection(Handler.java:74)
	- locked <7e002da38> (a sun.net.www.protocol.file.Handler)
	at sun.net.www.protocol.file.Handler.openConnection(Handler.java:55)
	- locked <7e002da38> (a sun.net.www.protocol.file.Handler)
	at java.net.URL.openConnection(URL.java:945)
	at java.net.URL.openStream(URL.java:1010)
	at javax.activation.URLDataSource.getInputStream(URLDataSource.java:92)
	at org.apache.axis.attachments.MimeUtils.getContentLength(MimeUtils.java:118)
	at org.apache.axis.attachments.MimeUtils.getContentLength(MimeUtils.java:63)
	at org.apache.axis.attachments.AttachmentsImpl.getContentLength(AttachmentsImpl.java:461)
	at org.apache.axis.Message.getContentLength(Message.java:513)
	at com.itko.lisa.ws.axis.LisaHTTPSender$MessageRequestEntity.getContentMessageLength(LisaHTTPSender.java:989)


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
It's hard to reproduce, but the stack traces are clear as to what the issue is

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
it should not deadlock
ACTUAL -
threads deadlock

REPRODUCIBILITY :
This bug can be reproduced occasionally.

CUSTOMER SUBMITTED WORKAROUND :
There are no work-arounds

Comments
Fix Request (8u) I would like to backport this patch to openjdk8u for parity with Oracle 8u291. The original patch does not apply cleanly, 8u patch has been reviewed.
22-06-2021

8u code review: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2021-June/013998.html
21-06-2021

Fix request (15u): applied as clean or more as for 13u (a context copyright difference only).
31-03-2021

Fix request (13u): I'd like to backport it to 13u as well. The patch goes clean barring copyright years difference. Will label after the tests completion.
28-01-2021

Fix Request (11u-dev) Should get backported for parity with 11.0.11-oracle. Doesn't apply cleanly. Review thread: http://mail.openjdk.java.net/pipermail/jdk-updates-dev/2021-January/004688.html
19-01-2021

Fix Request (16u): This fix would provide parity between 8u,11u and 16u. Risk of regression is low.
19-01-2021

Changeset: db9c114d Author: Jaikiran Pai <jpai@openjdk.org> Date: 2021-01-18 11:53:22 +0000 URL: https://git.openjdk.java.net/jdk/commit/db9c114d
18-01-2021

[~never] I think your right on URLStreamHandler.getHostAddress, that should be synchronized on u, not the handler. It looks like this bug has been existed for a long time.
05-01-2021

We recently tripped across this deadlock with WLS unit tests that use mockit. The full stack of the deadlock is: Found one Java-level deadlock: ============================= "Test worker": waiting to lock monitor 0x00007fdc70006218 (object 0x00000000f55c7f78, a sun.net.www.protocol.file.Handler), which is held by "LibGraalHotSpotGraalManagement-init" "LibGraalHotSpotGraalManagement-init": waiting to lock monitor 0x00007fdc700062c8 (object 0x00000000f55d2790, a java.util.HashMap), which is held by "Test worker"Java stack information for the threads listed above: =================================================== "Test worker": at java.net.URLStreamHandler.getHostAddress(URLStreamHandler.java:434) - waiting to lock <0x00000000f55c7f78> (a sun.net.www.protocol.file.Handler) at java.net.URLStreamHandler.hostsEqual(URLStreamHandler.java:461) at sun.net.www.protocol.file.Handler.hostsEqual(Handler.java:134) at java.net.URLStreamHandler.sameFile(URLStreamHandler.java:418) at java.net.URLStreamHandler.equals(URLStreamHandler.java:339) at java.net.URL.equals(URL.java:887) at java.security.CodeSource.equals(CodeSource.java:154) at java.util.HashMap.getNode(HashMap.java:572) at java.util.HashMap.get(HashMap.java:557) at java.security.SecureClassLoader.getProtectionDomain(SecureClassLoader.java:204) - locked <0x00000000f55d2790> (a java.util.HashMap) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) at java.net.URLClassLoader.access$100(URLClassLoader.java:74) at java.net.URLClassLoader$1.run(URLClassLoader.java:369) at java.net.URLClassLoader$1.run(URLClassLoader.java:363) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:362) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) - locked <0x00000000f804be90> (a java.lang.Object) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at mockit.external.asm.ClassReader.readConst(ClassReader.java:2490) at mockit.external.asm.ClassReader.copyBootstrapMethods(ClassReader.java:393) at mockit.external.asm.ClassReader.copyPool(ClassReader.java:340) at mockit.external.asm.ClassWriter.<init>(ClassWriter.java:1786) at mockit.internal.BaseClassModifier.<init>(BaseClassModifier.java:49) at mockit.internal.expectations.mocking.ExpectationsModifier.<init>(ExpectationsModifier.java:39) at mockit.internal.expectations.mocking.BaseTypeRedefinition.createClassModifier(BaseTypeRedefinition.java:156) at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineClassAndItsSuperClasses(BaseTypeRedefinition.java:196) at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineMethodsAndConstructorsInTargetType(BaseTypeRedefinition.java:185) at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineTargetClassAndCreateInstanceFactory(BaseTypeRedefinition.java:268) at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineType(BaseTypeRedefinition.java:67) at mockit.internal.expectations.mocking.TypeRedefinition.redefineType(TypeRedefinition.java:17) at mockit.internal.expectations.mocking.ParameterTypeRedefinitions.redefineMockedType(ParameterTypeRedefinitions.java:87) at mockit.internal.expectations.mocking.ParameterTypeRedefinitions.redefineMockedTypes(ParameterTypeRedefinitions.java:76) at mockit.internal.expectations.mocking.ParameterTypeRedefinitions.<init>(ParameterTypeRedefinitions.java:41) at mockit.integration.internal.TestRunnerDecorator.createInstancesForMockParameters(TestRunnerDecorator.java:189) at mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:150) at mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65) at mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:37) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:175) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:157) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) at java.lang.Thread.run(Thread.java:748) "LibGraalHotSpotGraalManagement-init": at java.security.SecureClassLoader.getProtectionDomain(SecureClassLoader.java:204) - waiting to lock <0x00000000f55d2790> (a java.util.HashMap) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) at java.net.URLClassLoader.access$100(URLClassLoader.java:74) at java.net.URLClassLoader$1.run(URLClassLoader.java:369) at java.net.URLClassLoader$1.run(URLClassLoader.java:363) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:362) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) - locked <0x00000000f829af10> (a java.lang.Object) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at mockit.internal.expectations.ReplayPhase.createExpectationIfNotStrictInvocation(ReplayPhase.java:101) at mockit.internal.expectations.ReplayPhase.handleInvocation(ReplayPhase.java:68) at mockit.internal.expectations.RecordAndReplayExecution.recordOrReplay(RecordAndReplayExecution.java:230) at mockit.internal.expectations.mocking.MockedBridge.invoke(MockedBridge.java:63) at java.io.File.<init>(File.java) at sun.net.www.protocol.file.Handler.openConnection(Handler.java:80) - locked <0x00000000f55c7f78> (a sun.net.www.protocol.file.Handler) at sun.net.www.protocol.file.Handler.openConnection(Handler.java:72) - locked <0x00000000f55c7f78> (a sun.net.www.protocol.file.Handler) at java.net.URL.openConnection(URL.java:1001) at sun.net.www.protocol.jar.JarURLConnection.<init>(JarURLConnection.java:84) at sun.net.www.protocol.jar.Handler.openConnection(Handler.java:41) at java.net.URL.openConnection(URL.java:1001) at java.net.URL.openStream(URL.java:1067) at java.util.ServiceLoader.parse(ServiceLoader.java:304) at java.util.ServiceLoader.access$200(ServiceLoader.java:185) at java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:357) at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393) at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:474) at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.findFactory(HotSpotJVMCIRuntime.java:407) at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.<init>(HotSpotJVMCIRuntime.java:507) at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime(HotSpotJVMCIRuntime.java:172) - locked <0x00000000f6476e00> (a java.lang.Class for jdk.vm.ci.runtime.JVMCI) at org.graalvm.libgraal.LibGraal.initializeLibgraal(LibGraal.java:89) at org.graalvm.libgraal.LibGraal.<clinit>(LibGraal.java:97) at org.graalvm.compiler.hotspot.management.LibGraalMBean$Factory.<init>(LibGraalMBean.java:620) at org.graalvm.compiler.hotspot.management.LibGraalMBean$Factory.<init>(LibGraalMBean.java:600) at org.graalvm.compiler.hotspot.management.LibGraalMBean.getFactory(LibGraalMBean.java:386) - locked <0x00000000f6487b08> (a java.lang.Class for org.graalvm.compiler.hotspot.management.LibGraalMBean) at org.graalvm.compiler.hotspot.management.JMXFromLibGraalEntryPoints.getFactory(JMXFromLibGraalEntryPoints.java:50) Here's the analysis from our internal JIRA issue. I don't see how this can be the fault of the management bean. It seems to me like mockit is the one creating the deadlock by triggering more class loading while the Handler is locked. at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at mockit.internal.expectations.ReplayPhase.createExpectationIfNotStrictInvocation(ReplayPhase.java:101) at mockit.internal.expectations.ReplayPhase.handleInvocation(ReplayPhase.java:68) at mockit.internal.expectations.RecordAndReplayExecution.recordOrReplay(RecordAndReplayExecution.java:230) at mockit.internal.expectations.mocking.MockedBridge.invoke(MockedBridge.java:63) at java.io.File.<init>(File.java) at sun.net.www.protocol.file.Handler.openConnection(Handler.java:80) - locked <0x00000000f55c7f78> (a sun.net.www.protocol.file.Handler) at sun.net.www.protocol.file.Handler.openConnection(Handler.java:72) - locked <0x00000000f55c7f78> (a sun.net.www.protocol.file.Handler) It seems to me that whole path in the JDK is dangerous since if any class loading occurs inside openConnection, then you might acquire the Handler and HashMap locks out of order relative to the SecureClassLoader.defineClass path. Maybe in practice this path performs any required class loading once so it's not generally exposed to the problem. at java.net.URLStreamHandler.getHostAddress(URLStreamHandler.java:434) - waiting to lock <0x00000000f55c7f78> (a sun.net.www.protocol.file.Handler) at java.net.URLStreamHandler.hostsEqual(URLStreamHandler.java:461) at sun.net.www.protocol.file.Handler.hostsEqual(Handler.java:134) at java.net.URLStreamHandler.sameFile(URLStreamHandler.java:418) at java.net.URLStreamHandler.equals(URLStreamHandler.java:339) at java.net.URL.equals(URL.java:887) at java.security.CodeSource.equals(CodeSource.java:154) at java.util.HashMap.getNode(HashMap.java:572) at java.util.HashMap.get(HashMap.java:557) at java.security.SecureClassLoader.getProtectionDomain(SecureClassLoader.java:204) - locked <0x00000000f55d2790> (a java.util.HashMap) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) https://bugs.openjdk.java.net/browse/JDK-7146776 and https://bugs.openjdk.java.net/browse/JDK-7177996 seem to be an examples of this problem that were never resolved. I think the root of the problem is that URLStreamHandler.getHostAddress is synchronizing on the wrong thing. It should be synchronizing on the URL and not the Handler since that's what's actually protecting URL.hostAddress, at least according to URL.set
05-01-2021

No recent interest or activity. Please re-open if there is future interest.
31-07-2017