[PHONEME-54] Classes not getting garbage collected automatically Created: 26/Oct/11  Updated: 26/Oct/11

Status: Open
Project: phoneme
Component/s: None
Affects Version/s: current
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Knut Anders Hatlen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Product: phoneME Advanced (phoneme_advanced_mr2-b168)
Profile: Foundation Profile Specification 1.1
JVM: CVM phoneme_advanced_mr2-b168 (interpreter loop)

Attachments: Java Source File ClassGC.java    


When running Apache Derby unit tests on phoneME, we frequently see
OutOfMemoryErrors (or sometimes java.lang.InternalError: Number of
class names exceeds vm limit). These errors appear to happen because
phoneME runs out of space for classes. However, if we add explicit
calls to System.gc(), the problems go away. So the problem seems to be
that phoneME doesn't automatically run garbage collection when it's
about to run out of space for classes.

phoneME should be able to detect that it's about to run out of class
space and invoke garbage collection, so that the applications don't
need to run garbage collection manually.

(This seems to be more of a problem when running with heap settings
higher than the default, as that would reduce the chance of the heap
getting full and implicitly triggering timely garbage collection.)

Comment by Knut Anders Hatlen [ 26/Oct/11 ]

Attached is a standalone repro for this problem. The repro does not
use Apache Derby, but simply loads a single class repeatedly, each
time in a new class loader. Since both the class loader and the class
instance are immediately eligible for garbage collection, one wouldn't
expect the application to run out of memory, but it does after less
than 5000 iterations:

$ cvm -Xms100M -Xmn100M -Xmx100M -cp . ClassGC
at java.lang.ClassLoader.InitializeLoaderGlobalRoot(Native Method)
at java.lang.ClassLoader.<init>(Unknown Source)
at java.security.SecureClassLoader.<init>(Unknown Source)
at java.net.URLClassLoader.<init>(Unknown Source)
at ClassGC.main(Unknown Source)
at sun.misc.CVM.runMain(Unknown Source)

Adding the flag -XunlimitedGCRoots makes it go on a little longer, but
it fails before it reaches 20000 iterations:

$ cvm -Xms100M -Xmn100M -Xmx100M -XunlimitedGCRoots -cp . ClassGC
java.lang.OutOfMemoryError: loading class "ClassGC"
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Unknown Source)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at ClassGC.main(Unknown Source)
at sun.misc.CVM.runMain(Unknown Source)

If I uncomment the System.gc() line in the repro, it doesn't run out
of memory. (I had it running 6 million iterations before I terminated

Generated at Mon Mar 27 22:31:12 UTC 2017 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.