JDK-8156824 : com.sun.jndi.ldap.pool.PoolCleaner should clear its context class loader
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.naming
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2016-05-11
  • Updated: 2019-01-14
  • Resolved: 2016-07-28
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 8 JDK 9
8u192Fixed 9 b130Fixed
Related Reports
Duplicate :  
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
The PoolCleaner thread started by the LdapPoolManager when the idle timeout is positive does not explicitly set the context class loader so it inherits the current context class loader. If the current context class loader when this code is triggered happens to be one that is meant to be disposable (e.g. a web application class loader) the class loader will be pinned in memory until the Thread stops. This prevents the class loader from being GC'd when no longer required and triggers a memory leak.

The fix looks to be trivial. Something along the lines of the following around line 45 of PoolCleaner:
setContextClassLoader(PoolCleaner.class.getClassLoader());

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the demonstration app:

https://github.com/markt-asf/memory-leaks/blob/master/src/org/apache/markt/leaks/ldap/PoolManagerLeak.java

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The expected result (on stdout) is:
One call to GC was required, as expected.
No leak
ACTUAL -
The actual result (on stdout) is:
There were 3 calls to GC. Ideally, only one should be required.
Leak

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
https://github.com/markt-asf/memory-leaks/blob/master/src/org/apache/markt/leaks/ldap/PoolManagerLeak.java
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
The work-around is to call 

Class.forName("com.sun.jndi.ldap.LdapPoolManager");

when the context class loader is a class loader than is not expected to become eligable for GC during the lifetime of the JVM.


Comments
Internal platform threads should null out the context class loader, see JDK-8160513, JDK-8157570.
28-07-2016