JDK-8157570 : sun.rmi.transport.GC retains a strong reference to the context class loader
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.rmi
  • Affected Version: 8,9
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2016-05-20
  • Updated: 2017-05-11
  • 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 9
9 b130Fixed
Related Reports
Duplicate :  
Relates :  
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 thread created by the GC class does not explicitly set the context
class loader so it inherits the current context class loader. 

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Consider the following sequence where each module has a dedicated class loader (e.g. web applications in a Servlet container).

Module A starts an RMIConnectorServer instance. Amongst other things it
calls GC.requestLatency(long) which starts the Daemon thread.

Module B starts another RMIConnectorServer instance. It also calls
GC.requestLatency(long) and the Daemon thread continues.

Module A shuts down the RMIConnectorServer and does all the right
clean-up. The associated LatencyRequest is cancelled but the Daemon
thread continues because of the LatencyRequest from Module B.

At this point there is a memory leak because the class loader associated
with module A is pinned in memory since a reference to it is held by the
context class loader field of the Daemon thread.

The fix looks to be trivial. Something along the lines of the following
around line 146 of GC:

d.setContextClassLoader(GC.class.getClassLoader());

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The class loader from module A is eligible for GC.
ACTUAL -
The class loader from module A is not eligible for GC.

REPRODUCIBILITY :
This bug can be reproduced always.

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

CUSTOMER SUBMITTED WORKAROUND :
Trigger the creation of the thread with a thread context class loader than is never going to be eligible for GC.


Comments
The GC.Daemon thread should set its context class to null, or possibly use an InnocuousThread with a null context class loader. Can it be backported? Yes, possibly.
28-07-2016

This issue is similar to JDK-8160513.
26-07-2016

Ran the attached test case on JDK 8u92 and JDK 9ea , following is the output on both versions: >java GcThreadLeak One call to GC was required, as expected. No leak
23-05-2016