]
Brian Stansberry updated WFLY-11678:
------------------------------------
Fix Version/s: 16.0.0.CR1
(was: 16.0.0.Beta1)
ManagedExecutorService persists contextClassLoader reference to cause
app classloader leaks
-------------------------------------------------------------------------------------------
Key: WFLY-11678
URL:
https://issues.jboss.org/browse/WFLY-11678
Project: WildFly
Issue Type: Bug
Components: Concurrency Utilities
Environment: -- EAP 7.1.4
Reporter: Lei Yu
Assignee: James Perkins
Priority: Critical
Fix For: 16.0.0.CR1
managed executor:
{code}
<managed-executor-services>
<managed-executor-service name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default" hung-task-threshold="60000"
keepalive-time="5000"/>
</managed-executor-services>
{code}
With each undeploy, the application classloader is leaked and not released because
contextClassLoader references persisted on the executor threads:
{code}
Class Name
| Ref. Objects | Shallow Heap |
Ref. Shallow Heap | Retained Heap
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
org.jboss.as.ee.concurrent.service.ElytronManagedThreadFactory$ElytronManagedThread @
0xc3677570 EE-ManagedExecutorService-default-Thread-13 Thread| 1 |
160 | 88 | 1,344
'- contextClassLoader org.jboss.modules.ModuleClassLoader @ 0xc32b9d98
| 1 |
88 | 88 | 366,800
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{code}
Tracing with byteman, what's strange is that it sets the app classloader on setup:
{code}
Thread.setContextClassLoader:
Thread[EE-ManagedExecutorService-default-Thread-16,5,ServerService ThreadGroup]
ModuleClassLoader for Module "deployment.services-1.0.4-rc1.war" from Service
Module Loader
java.lang.Thread.setContextClassLoader(Thread.java:1477)
org.wildfly.security.manager.WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(WildFlySecurityManager.java:1272)
org.jboss.as.ee.concurrent.handle.ClassLoaderContextHandleFactory$ClassLoaderSetupContextHandle.setup(ClassLoaderContextHandleFactory.java:83)
org.jboss.as.ee.concurrent.ConcurrentContext$ChainedSetupContextHandle.setup(ConcurrentContext.java:166)
org.jboss.as.ee.concurrent.DefaultContextSetupProviderImpl.setup(DefaultContextSetupProviderImpl.java:58)
org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.setupContext(ManagedFutureTask.java:121)
org.glassfish.enterprise.concurrent.internal.ManagedThreadPoolExecutor.beforeExecute(ManagedThreadPoolExecutor.java:109)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
java.lang.Thread.run(Thread.java:748)
{code}
And still sets that app classloader after task execution in the reset:
{code}
Thread.setContextClassLoader:
Thread[EE-ManagedExecutorService-default-Thread-16,5,ServerService ThreadGroup]
ModuleClassLoader for Module "deployment.services-1.0.4-rc1.war" from Service
Module Loader
java.lang.Thread.setContextClassLoader(Thread.java:1477)
org.wildfly.security.manager.WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(WildFlySecurityManager.java:1272)
org.jboss.as.ee.concurrent.handle.ClassLoaderContextHandleFactory$ClassLoaderResetContextHandle.reset(ClassLoaderContextHandleFactory.java:113)
org.jboss.as.ee.concurrent.ConcurrentContext$ChainedResetContextHandle.reset(ConcurrentContext.java:284)
org.jboss.as.ee.concurrent.DefaultContextSetupProviderImpl.reset(DefaultContextSetupProviderImpl.java:63)
org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.resetContext(ManagedFutureTask.java:134)
org.glassfish.enterprise.concurrent.internal.ManagedThreadPoolExecutor.afterExecute(ManagedThreadPoolExecutor.java:90)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1157)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
java.lang.Thread.run(Thread.java:748)
{code}
So the thread is sitting in the pool with the app classloader. Is there some way we
should be able to get the context loader cleared or unset from the app loader in the
reset?