#51463·Spring Boot

Threads are blocked with virtual threads active while waiting for a lock to load classes with JarUrlClassLoader

Author: nalischCreated Aug 26, 2026Updated Sep 17, 2026
Labelsstatus: waiting-for-triagestatus: feedback-provided

Used versions Spring Boot 4.1.0 OpenJDK 64-Bit Server VM (25.0.4+7-LTS mixed mode, sharing)

Describe the bug While startup of our Spring Boot application, threads are blocked because they are waiting for a lock to load classes from the java.base module with org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader. The application is not responding to any request.

In the following thread dump the entry at org.springframework.boot.loader.jar.NestedJarFile.hasEntry(NestedJarFile.java:251) - waiting to lock <0x00000000e165a528> (a org.springframework.boot.loader.net.protocol.jar.UrlNestedJarFile) is existent twice in two different threads.

The Catalina-utility-2 thread is blocked.

Full thread dump OpenJDK 64-Bit Server VM (25.0.4+7-LTS mixed mode, sharing):
Threads class SMR info:
_java_thread_list=0x00007f9e7dfba470, length=24, elements={
0x00007f9e888d8680, 0x00007f9e888b8170, 0x00007f9e888b8c20, 0x00007f9e888b96d0,
0x00007f9e888b5030, 0x00007f9e888b5940, 0x00007f9e888b6270, 0x00007f9e888b74f0,
0x00007f9e88003030, 0x00007f9e88005500, 0x00007f9e80f2c260, 0x00007f9e80f2b900,
0x00007f9e80f2cb60, 0x00007f9e806ebb50, 0x00007f9e806ec480, 0x00007f9e806ecd50,
0x00007f9e806ed6c0, 0x00007f9e7f81fd70, 0x00007f9e7f821020, 0x00007f9e7f822240,
0x00007f9e7f823db0, 0x00007f9e880039a0, 0x00007f9e7e966740, 0x00007f9e7f81c6b0
}
"Reference Handler" #12 [16] daemon prio=10 os_prio=0 cpu=7.11ms elapsed=25185.63s tid=0x00007f9e888d8680 nid=16 waiting on condition  [0x00007f9e88577000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.ref.Reference.waitForReferencePendingList([email protected]/Native Method)
	at java.lang.ref.Reference.processPendingReferences([email protected]/Unknown Source)
	at java.lang.ref.Reference$ReferenceHandler.run([email protected]/Unknown Source)
"Finalizer" #13 [17] daemon prio=8 os_prio=0 cpu=0.35ms elapsed=25185.63s tid=0x00007f9e888b8170 nid=17 in Object.wait()  [0x00007f9e88474000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait0([email protected]/Native Method)
	- waiting on <0x00000000e01000e8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.Object.wait([email protected]/Unknown Source)
	at java.lang.Object.wait([email protected]/Unknown Source)
	at java.lang.ref.ReferenceQueue.remove0([email protected]/Unknown Source)
	at java.lang.ref.ReferenceQueue.remove([email protected]/Unknown Source)
	- locked <0x00000000e01000e8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.Finalizer$FinalizerThread.run([email protected]/Unknown Source)
"Signal Dispatcher" #14 [18] daemon prio=9 os_prio=0 cpu=0.35ms elapsed=25185.63s tid=0x00007f9e888b8c20 nid=18 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"Service Thread" #15 [19] daemon prio=9 os_prio=0 cpu=932.95ms elapsed=25185.63s tid=0x00007f9e888b96d0 nid=19 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"Monitor Deflation Thread" #16 [20] daemon prio=9 os_prio=0 cpu=2957.73ms elapsed=25185.63s tid=0x00007f9e888b5030 nid=20 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #17 [21] daemon prio=9 os_prio=0 cpu=26579.67ms elapsed=25185.63s tid=0x00007f9e888b5940 nid=21 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task
"C1 CompilerThread0" #18 [22] daemon prio=9 os_prio=0 cpu=7706.32ms elapsed=25185.63s tid=0x00007f9e888b6270 nid=22 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task
"Notification Thread" #19 [23] daemon prio=9 os_prio=0 cpu=19.86ms elapsed=25185.62s tid=0x00007f9e888b74f0 nid=23 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"Common-Cleaner" #20 [24] daemon prio=8 os_prio=0 cpu=30.03ms elapsed=25185.62s tid=0x00007f9e88003030 nid=24 in Object.wait()  [0x00007f9e83c9d000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait0([email protected]/Native Method)
	- waiting on <no object reference available>
	at java.lang.Object.wait([email protected]/Unknown Source)
	at java.lang.ref.ReferenceQueue.remove0([email protected]/Unknown Source)
	at java.lang.ref.ReferenceQueue.remove([email protected]/Unknown Source)
	- locked <0x00000000e01001b0> (a java.lang.ref.ReferenceQueue$Lock)
	at jdk.internal.ref.CleanerImpl.run([email protected]/Unknown Source)
	at java.lang.Thread.runWith([email protected]/Unknown Source)
	at java.lang.Thread.run([email protected]/Unknown Source)
	at jdk.internal.misc.InnocuousThread.run([email protected]/Unknown Source)
"Cleaner-0" #21 [25] daemon prio=8 os_prio=0 cpu=42.06ms elapsed=25185.43s tid=0x00007f9e88005500 nid=25 in Object.wait()  [0x00007f9e839d0000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait0([email protected]/Native Method)
	- waiting on <no object reference available>
	at java.lang.Object.wait([email protected]/Unknown Source)
	at java.lang.ref.ReferenceQueue.remove0([email protected]/Unknown Source)
	at java.lang.ref.ReferenceQueue.remove([email protected]/Unknown Source)
	- locked <0x00000000e0100270> (a java.lang.ref.ReferenceQueue$Lock)
	at jdk.internal.ref.CleanerImpl.run([email protected]/Unknown Source)
	at java.lang.Thread.runWith([email protected]/Unknown Source)
	at java.lang.Thread.run([email protected]/Unknown Source)
	at jdk.internal.misc.InnocuousThread.run([email protected]/Unknown Source)
"Catalina-utility-1" #28 [30] prio=1 os_prio=0 cpu=2262.02ms elapsed=25173.33s tid=0x00007f9e80f2c260 nid=30 waiting on condition  [0x00007f9e80aca000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
	- parking to wait for  <0x00000000e1f00278> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos([email protected]/Unknown Source)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos([email protected]/Unknown Source)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take([email protected]/Unknown Source)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take([email protected]/Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.getTask([email protected]/Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker([email protected]/Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run([email protected]/Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:74)
	at java.lang.Thread.runWith([email protected]/Unknown Source)
	at java.lang.Thread.run([email protected]/Unknown Source)
"Catalina-utility-2" #29 [31] prio=1 os_prio=0 cpu=1555.76ms elapsed=25173.33s tid=0x00007f9e80f2b900 nid=31 waiting for monitor entry  [0x00007f9e8089c000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at org.springframework.boot.loader.jar.NestedJarFile.hasEntry(NestedJarFile.java:251)
	- waiting to lock <0x00000000e165a528> (a org.springframework.boot.loader.net.protocol.jar.UrlNestedJarFile)
	at org.springframework.boot.loader.net.protocol.jar.JarUrlConnection.hasEntry(JarUrlConnection.java:356)
	at org.springframework.boot.loader.net.protocol.jar.JarUrlConnection.open(JarUrlConnection.java:347)
	at org.springframework.boot.loader.net.protocol.jar.Handler.openConnection(Handler.java:46)
	at java.net.URL.openConnection([email protected]/Unknown Source)
	at jdk.internal.loader.URLClassPath$Loader.getResource([email protected]/Unknown Source)
	at jdk.internal.loader.URLClassPath.getResource([email protected]/Unknown Source)
	at java.net.URLClassLoader.findClass([email protected]/Unknown Source)
	at java.lang.ClassLoader.loadClass([email protected]/Unknown Source)
	- locked <0x00000000f01289a8> (a java.lang.Object)
	at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.loadClass(JarUrlClassLoader.java:107)
	at org.springframework.boot.loader.launch.LaunchedClassLoader.loadClass(LaunchedClassLoader.java:91)
	at java.lang.ClassLoader.loadClass([email protected]/Unknown Source)
	at org.apache.catalina.core.ContainerBase.getClusterInternal(ContainerBase.java:342)
	at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:931)
	- locked <0x00000000e2d16b50> (a org.apache.catalina.core.StandardWrapper)
	at org.apache.catalina.core.StandardWrapper.backgroundProcess(StandardWrapper.java:474)
	- locked <0x00000000e2d16b50> (a org.apache.catalina.core.StandardWrapper)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1179)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1183)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1183)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1183)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1156)
	at java.util.concurrent.Executors$RunnableAdapter.call([email protected]/Unknown Source)
	at java.util.concurrent.FutureTask.runAndReset([email protected]/Unknown Source)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run([email protected]/Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker([email protected]/Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run([email protected]/Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:74)
	at java.lang.Thread.runWith([email protected]/Unknown Source)
	at java.lang.Thread.run([email protected]/Unknown Source)
"container-0" #30 [32] prio=5 os_prio=0 cpu=126.99ms elapsed=25173.31s tid=0x00007f9e80f2cb60 nid=32 waiting on condition  [0x00007f9e804ab000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleepNanos0([email protected]/Native Method)
	at java.lang.Thread.sleepNanos([email protected]/Unknown Source)
	at java.lang.Thread.sleep([email protected]/Unknown Source)
	at org.apache.catalina.core.StandardServer.await(StandardServer.java:522)
	at org.springframework.boot.tomcat.TomcatWebServer$1.run(TomcatWebServer.java:216)
"HttpClient-1-SelectorManager" #47 [49] daemon prio=5 os_prio=0 cpu=480.50ms elapsed=25168.17s tid=0x00007f9e806ebb50 nid=49 runnable  [0x00007f9e7f973000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPoll.wait([email protected]/Native Method)
	at sun.nio.ch.EPollSelectorImpl.doSelect([email protected]/Unknown Source)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect([email protected]/Unknown Source)
	- locked <0x00000000e52800e8> (a sun.nio.ch.Util$2)
	- locked <0x00000000e5280098> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select([email protected]/Unknown Source)
	at jdk.internal.net.http.HttpClientImpl$SelectorManager.run([email protected]/Unknown Source)
"HttpClient-2-SelectorManager" #48 [50] daemon prio=5 os_prio=0 cpu=494.79ms elapsed=25168.14s tid=0x00007f9e806ec480 nid=50 runnable  [0x00007f9e7f6a0000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPoll.wait([email protected]/Native Method)
	at sun.nio.ch.EPollSelectorImpl.doSelect([email protected]/Unknown Source)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect([email protected]/Unknown Source)
	- locked <0x00000000e52803d8> (a sun.nio.ch.Util$2)
	- locked <0x00000000e5280388> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select([email protected]/Unknown Source)
	at jdk.internal.net.http.HttpClientImpl$SelectorManager.run([email protected]/Unknown Source)
"HttpClient-3-SelectorManager" #49 [51] daemon prio=5 os_prio=0 cpu=497.89ms elapsed=25168.12s tid=0x00007f9e806ecd50 nid=51 runnable  [0x00007f9e7f59d000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPoll.wait([email protected]/Native Method)
	at sun.nio.ch.EPollSelectorImpl.doSelect([email protected]/Unknown Source)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect([email protected]/Unknown Source)
	- locked <0x00000000e5280518> (a sun.nio.ch.Util$2)
	- locked <0x00000000e52804c8> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select([email protected]/Unknown Source)
	at jdk.internal.net.http.HttpClientImpl$SelectorManager.run([email protected]/Unknown Source)
"HttpClient-4-SelectorManager" #50 [52] daemon prio=5 os_prio=0 cpu=481.95ms elapsed=25168.11s tid=0x00007f9e806ed6c0 nid=52 runnable  [0x00007f9e7f49a000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPoll.wait([email protected]/Native Method)
	at sun.nio.ch.EPollSelectorImpl.doSelect([email protected]/Unknown Source)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect([email protected]/Unknown Source)
	- locked <0x00000000e5280658> (a sun.nio.ch.Util$2)
	- locked <0x00000000e5280608> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select([email protected]/Unknown Source)
	at jdk.internal.net.http.HttpClientImpl$SelectorManager.run([email protected]/Unknown Source)
"http-nio-4090-Poller" #52 [54] daemon prio=5 os_prio=0 cpu=1894.88ms elapsed=25160.73s tid=0x00007f9e7f81fd70 nid=54 runnable  [0x00007f9e7e57e000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPoll.wait([email protected]/Native Method)
	at sun.nio.ch.EPollSelectorImpl.doSelect([email protected]/Unknown Source)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect([email protected]/Unknown Source)
	- locked <0x00000000e98800f0> (a sun.nio.ch.Util$2)
	- locked <0x00000000e98800a0> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select([email protected]/Unknown Source)
	at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:912)
	at java.lang.Thread.runWith([email protected]/Unknown Source)
	at java.lang.Thread.run([email protected]/Unknown Source)
"http-nio-4090-Acceptor" #53 [55] daemon prio=5 os_prio=0 cpu=73.61ms elapsed=25160.73s tid=0x00007f9e7f821020 nid=55 runnable  [0x00007f9e7dcca000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.Net.accept([email protected]/Native Method)
	at sun.nio.ch.ServerSocketChannelImpl.implAccept([email protected]/Unknown Source)
	at sun.nio.ch.ServerSocketChannelImpl.accept([email protected]/Unknown Source)
	at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:626)
	at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:71)
	at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:145)
	at java.lang.Thread.runWith([email protected]/Unknown Source)
	at java.lang.Thread.run([email protected]/Unknown Source)
"VirtualThread-unblocker" #54 [56] daemon prio=5 os_prio=0 cpu=0.97ms elapsed=25160.64s tid=0x00007f9e7f822240 nid=56 runnable  [0x00007f9e7dbc8000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.VirtualThread.takeVirtualThreadListToUnblock([email protected]/Native Method)
	at java.lang.VirtualThread.unblockVirtualThreads([email protected]/Unknown Source)
	at java.lang.VirtualThread$$Lambda/0x000000000d7e1730.run([email protected]/Unknown Source)
	at java.lang.Thread.runWith([email protected]/Unknown Source)
	at java.lang.Thread.run([email protected]/Unknown Source)
	at jdk.internal.misc.InnocuousThread.run([email protected]/Unknown Source)
"ForkJoinPool-1-delayScheduler" #58 [59] daemon prio=5 os_prio=0 cpu=24.31ms elapsed=25160.54s tid=0x00007f9e7f823db0 nid=59 waiting on condition  [0x00007f9e7e113000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
	at java.util.concurrent.DelayScheduler.loop([email protected]/Unknown Source)
	at java.util.concurrent.DelayScheduler.run([email protected]/Unknown Source)
"DestroyJavaVM" #60 [7] prio=5 os_prio=0 cpu=16972.45ms elapsed=25160.27s tid=0x00007f9e880039a0 nid=7 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"ForkJoinPool-1-worker-107" #179 [164] daemon prio=5 os_prio=0 cpu=996.50ms elapsed=22002.89s tid=0x00007f9e7e966740  [0x00007f9e7e67f000]
   Carrying virtual thread #178
	at jdk.internal.vm.Continuation.run([email protected]/Unknown Source)
	at java.lang.VirtualThread.runContinuation([email protected]/Unknown Source)
	at java.lang.VirtualThread$$Lambda/0x000000000d7e1e00.run([email protected]/Unknown Source)
	at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute([email protected]/Unknown Source)
	at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute([email protected]/Unknown Source)
	at java.util.concurrent.ForkJoinTask$InterruptibleTask.exec([email protected]/Unknown Source)
	at java.util.concurrent.ForkJoinTask.doExec([email protected]/Unknown Source)
	at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec([email protected]/Unknown Source)
	at java.util.concurrent.ForkJoinPool.runWorker([email protected]/Unknown Source)
	at java.util.concurrent.ForkJoinWorkerThread.run([email protected]/Unknown Source)
   Mounted virtual thread #178
	at org.springframework.boot.loader.jar.NestedJarFile.hasEntry(NestedJarFile.java:251)
	- waiting to lock <0x00000000e165a528> (a org.springframework.boot.loader.net.protocol.jar.UrlNestedJarFile)
	at org.springframework.boot.loader.net.protocol.jar.JarUrlConnection.hasEntry(JarUrlConnection.java:356)
	at org.springframework.boot.loader.net.protocol.jar.JarUrlConnection.open(JarUrlConnection.java:347)
	at org.springframework.boot.loader.net.protocol.jar.Handler.openConnection(Handler.java:46)
	at java.net.URL.openConnection([email protected]/Unknown Source)
	at jdk.internal.loader.URLClassPath$Loader.getResource([email protected]/Unknown Source)
	at jdk.internal.loader.URLClassPath.getResource([email protected]/Unknown Source)
	at java.net.URLClassLoader.findClass([email protected]/Unknown Source)
	at java.lang.ClassLoader.loadClass([email protected]/Unknown Source)
	- locked <0x00000000f0983348> (a java.lang.Object)
	at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.loadClass(JarUrlClassLoader.java:107)
	at org.springframework.boot.loader.launch.LaunchedClassLoader.loadClass(LaunchedClassLoader.java:91)
	at java.lang.ClassLoader.loadClass([email protected]/Unknown Source)
	at org.springframework.expression.spel.support.ReflectionHelper.compareArguments(ReflectionHelper.java:67)
	at org.springframework.expression.spel.support.ReflectiveMethodResolver.resolve(ReflectiveMethodResolver.java:179)
	at org.springframework.expression.spel.ast.MethodReference.findMethodExecutor(MethodReference.java:286)
	at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:187)
	at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:125)
	at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:198)
	at org.springframework.expression.spel.ast.OpOr.getBooleanValue(OpOr.java:59)
	at org.springframework.expression.spel.ast.OpOr.getValueInternal(OpOr.java:50)
	at org.springframework.expression.spel.ast.OpOr.getValueInternal(OpOr.java:39)
	at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:114)
	at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:267)
	at org.springframework.security.authorization.method.ExpressionUtils.evaluate(ExpressionUtils.java:45)
	at org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager.authorize(PreAuthorizeAuthorizationManager.java:88)
	at org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager.authorize(PreAuthorizeAuthorizationManager.java:42)
	at org.springframework.security.authorization.ObservationAuthorizationManager.authorize(ObservationAuthorizationManager.java:75)
	at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.attemptAuthorization(AuthorizationManagerBeforeMethodInterceptor.java:252)
	at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.invoke(AuthorizationManagerBeforeMethodInterceptor.java:197)

Source: spring-projects/spring-boot