Bug 26351 - Native Momory Leak in ResourceBundle
Summary: Native Momory Leak in ResourceBundle
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libgcj (show other bugs)
Version: 3.4.5
: P3 major
Target Milestone: 4.0.3
Assignee: Tom Tromey
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-02-18 13:38 UTC by fexx
Modified: 2006-03-07 17:08 UTC (History)
3 users (show)

See Also:
Host: mingw32
Target: mingw32
Build: mingw32
Known to work:
Known to fail:
Last reconfirmed: 2006-03-07 16:58:24


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description fexx 2006-02-18 13:38:23 UTC
Invoking java.util.ResourceBundle.getBundle(String) leaks some native memory.  A small sample program is attached.  If you run it, you will see that the process' virual memory size keeps growing while Java heap consumption stays at a same level after some iteration.

The problem is in gnu.gcj.runtime.StackTrace.fillInStackTrace (a native code) invoked through gnu.gcj.runtime.StackTrace.classAt through java.lang.Class.forName through java.util.ResourceBundle.tryBundle.  When the native method fillInStackTrace is invoked by a method other than its constructor, a native memory allocated through _Jv_Malloc and stored in addrs is discarded without _Jv_Free'ed.

I exprerienced this problem on Windows (MinGW) but I belive it is common to other platforms.

A suggested fix is attached:

--- libjava/gnu/gcj/runtime/natStackTrace.orig.cc	2003-10-02 16:10:34.000000000 +0900
+++ libjava/gnu/gcj/runtime/natStackTrace.cc	2006-02-17 00:01:52.529572700 +0900
@@ -85,6 +85,8 @@
   else
     frame = NULL;
 
+  if (addrs != NULL)
+    _Jv_Free (addrs);
   addrs = reinterpret_cast<gnu::gcj::RawData *> (frame);
 #else // HAVE_BACKTRACE
   (void)maxlen;

---

A sample program to reproduce the problem follows:

import java.util.ResourceBundle;
import java.util.MissingResourceException;

public class Leak {
    public static void main(String[] args) {
	final Runtime r = Runtime.getRuntime();
	for (;;) {
	    for (int i = 0; i < 10000; i++) {
		try {
		    ResourceBundle.getBundle("nothing");
		} catch (MissingResourceException e) {
		}
	    }
	    System.out.println(r.freeMemory() + "/" + r.totalMemory());
	}
    }
}
Comment 1 Andrew Pinski 2006-02-20 02:24:24 UTC
Hmm, natStackTrace.cc was removed with:
2005-03-10  Bryce McKinlay  <mckinlay@redhat.com>
        
        New Stack Trace infrastructure.


So maybe this has been fixed for 4.1.0.

Also are you sure that it is leaking or just not being free right away?

I get the following behavior on powerpc-darwin on the mainline:
1294336/2060288
868352/2060288
425984/2060288
1650688/2060288
1318912/2060288
884736/2060288
450560/2060288
12288/2060288
1347584/2060288

See how it goes down and then back up?

Comment 2 Bryce McKinlay 2006-02-20 19:47:25 UTC
You must be using a very old GCJ - this was fixed a long time ago.

*** This bug has been marked as a duplicate of 12475 ***
Comment 3 fexx 2006-02-21 14:52:36 UTC
I belive this is another bug than 12475.  (I'm using libgcj come with gcc 3.4.5 distribution.)

PR 12475 stated that, when an Exception was initialized, a constructor
gnu.gcj.runtime.StackTrace(int) was indirectly invoked, and the native
memory allocated and set to StackTrace.addrs in
StackTrace.fillInStackTrace(int,int) leaked.  Hence, the fix to 12475
freed the (leaked) native memory in gnu.gcj.finalize().

This one, PR 26351, is a problem regarding some use of
gnu.gcj.runtime.StackTrace.classAt(int).  It causes two (or more)
invokation of StackTrace.fillInStackTrace(int,int) against a same
StackTrace object, once from its constructor, and once more from
classAt(int).  Every invokation of fillInStackTrace(int,int) allocates
a new native memory through _Jv_Malloc() and store it in addrs.  The
second invokation silently discards the native memory allocated during
the first, causing a leak.  _Jv_Free in finalize() doesn't help.

(Please note that the macro GET_FRAME used in the native method
StackTrace.classAt(int) *may* invoke fillInStackTrace *when* N is
larger than expected.)

There may be another execution paths, but calling
java.util.ResourceBundle.getBundle(String) was the easiest case that I could find.
Comment 4 Tom Tromey 2006-03-07 16:58:24 UTC
3.4.x is closed, we won't be putting any bug fixes on that branch.
(I think the next 3.4.x release will be the last one ever.)

This bug does seem to appear on the 4.0 branch.
I think I'll check in your patch, it seems to be ok.

This bug doesn't appear in the 4.1 series or later.
Comment 5 Tom Tromey 2006-03-07 17:07:44 UTC
Subject: Bug 26351

Author: tromey
Date: Tue Mar  7 17:07:37 2006
New Revision: 111814

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=111814
Log:
2006-03-07  fexx  <fexx@fexx.org>

	PR libgcj/26351:
	* gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Free
	'addrs' if it is set.

Modified:
    branches/gcc-4_0-branch/libjava/ChangeLog
    branches/gcc-4_0-branch/libjava/gnu/gcj/runtime/natStackTrace.cc

Comment 6 Tom Tromey 2006-03-07 17:08:46 UTC
Fix checked in.