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()); } } }
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?
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 ***
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.
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.
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
Fix checked in.