JDK-4858370 : JDWP: Memory Leak: GlobalRefs never deleted when processing invokeMethod command
  • Type: Bug
  • Component: core-svc
  • Sub-Component: debugger
  • Affected Version: 1.4.1,8u74,9
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2003-05-05
  • Updated: 2022-01-03
  • Resolved: 2016-03-22
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 Other
8u102Fixed 9 b115Fixed openjdk7uFixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description

Name: tb29552			Date: 05/05/2003


FULL PRODUCT VERSION :
java version "1.4.1_02"

Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)

Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)


FULL OS VERSION :
Linux boulette 2.4.19-k7 #1 Tue Nov 19 03:01:13 EST 2002 i686 unknown unknown GNU/Linux

A DESCRIPTION OF THE PROBLEM :
When a method is to be called in the target JVM by the mean of the JDWP command "invokeMethod" (accessed for example with the "print" feature in jdb), the implementation of JDWP (on any platform) makes global references for every Object that is implied in the method invocation: Thread that executes the call, Class that contains the method to call (eventually Instance in which the method will be called) and method arguments which type is Object. This is done in fillInvokeRequest() in file j2se/src/share/back/invoker.c.

When the method invocation terminates, global references are also created for the returned argument (if it is an Object) and for Exception that might have been thrown.

These global refs are created to be sure that objects implied in the invocation will not be collected by the GC until the JDWP command is fully processed.



When the result of the invocation is to be returned by JDWP, the global reference for the exception is deleted (at function invoker_completeInvokeRequest() in file j2se/src/share/back/invoker.c). A globalref retained for the execution thread is deleted too (at handleReportInvokeDoneCommand() in file j2se/src/share/back/eventHelper).



At this time, the request is fully processed but globalreferences created for arguments are never deleted, which is an very annoying memory leak.



A clean way to fix this memory leak is to modify function invoker_completeInvokeRequest() as followed:

void

invoker_completeInvokeRequest(jthread thread)

{

    // the beginning of the function stays the same.

    // I only added code to its end.

    ...

    ...

    ...



    if (!detached) {

        outStream_initReply(&out, id);

        outStream_writeValue(env, &out, tag, returnValue);

        outStream_writeObjectTag(&out, exc);

        WRITE_GLOBAL_REF(env, &out, exc);

        outStream_sendReply(&out);

    }



    // here comes the change...

    /*

     * At this time, there's no need to retain global references on

     * arguments since the reply is processed. No one will deal with

     * this request ID anymore, so we must call deleteGlobalRef().

     */

    deleteGlobalRefs(env, request);

    if ((request->invokeType == INVOKE_CONSTRUCTOR) ||

	(returnTypeTag(request->methodSignature) == JDWP_Tag_OBJECT)) {

      (*env)->DeleteGlobalRef(env, request->returnValue.l);

    }

}




STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
When using jdb and that the debuggee is suspended in method foo(Object bar), just type "print bar.toString()" to trigger the JDWP command "invokeMethod".

The problem can also be reproduced with jdk 1.4.2-beta




EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
GlobalRefs created during the process of the command should all be deleted.  This must be done here because they cannot be freed later by any other agent (such as a custom debugger or custom profiler) started in the target JVM.

ACTUAL -
GlobalRefs created for arguments of the method invocation are never deleted. This is responsible of an horrible memory leak !

My custom debugger/profiler uses JDWP to invoke a custom method in the target JVM  that will request JVMPI heap dump to know every alive objects that are referencing a particular JVM Object. Because of this memory leak, my debugger always return wrong informations, i.e it reports GlobalRefs on Objects while actually no GlobalRef has been allocated by the debugged program itself :(


ERROR MESSAGES/STACK TRACES THAT OCCUR :
(no error displayed on screen)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class incoming2 {

    public static void main(String[] args) {

        // break into main and do "print c1.toString()" in jdb

	Class c1=Object.class;

	System.out.println("1st: "+c1);

    }

}



---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
This should really be fixed in JVM-side, since it's JDWP that is responsible of the allocation of the GlobalRefs.
(Review ID: 185252) 
======================================================================

Comments
URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/277d7584fa03 User: lana Date: 2016-04-20 17:52:51 +0000
20-04-2016

This fix caused some test regressions and was backed out of JDK9-hs-rt using the following: JDK-8153673 [BACKOUT] JDWP: Memory Leak: GlobalRefs never deleted when processing invokeMethod command
11-04-2016

This fix and test was backed out in JDK9-hs-rt via: JDK-8153673
07-04-2016

URL: http://hg.openjdk.java.net/jdk9/hs-rt/jdk/rev/277d7584fa03 User: sspitsyn Date: 2016-03-22 23:15:22 +0000
22-03-2016

Posted patch for review: http://mail.openjdk.java.net/pipermail/serviceability-dev/2016-March/019155.html
21-03-2016

PUBLIC COMMENTS .
10-06-2004

EVALUATION ###@###.### 2003-05-05 In this case there needs to be automatic cleanup/GC of global resources allocated. But see also bug 4257193, which is a request for more explicit control over the lifetime of Objects created in the debugee VM on behalf of the debugger. ###@###.### 2003-05-06 Committing to the same release as 4257193. These bugfixes will be considered together.
06-05-2003