JVM Tutorials - Herong's Tutorial Examples - Version 4.23, by Dr. Herong Yang
Garbage Collection Issue with Dynamically Generated Classes
This section provides a tutorial example that shows the JVM garbage collector is struggling to maintain the Heap data area with dynamically generated classes. It spends about 89% of the time doing MarkSweepCompact garbage collection.
While watching "jconsole" connected to the MethodAreaDynamicClass.java execution JVM, I saw the number of classes growing, which causes the size of the Method Area to grow as expected. But I also saw the Heap memory usage growing too. I am not sure why.
If both data areas are growing, we should soon get an OutOfMemoryError exception on the Method Area or on the Heap, right?
Wrong answer. The JVM continues to run for long time, and spends more and more time on garbage collection, and less and less time generating new classes.
Here is the summary of the JVM after 1 hour of the execution time:
Connection name: pid: 2860 MethodAreaDynamicClass
Virtual Machine: Java HotSpot(TM) Client VM version 25.0-b70
Vendor: Oracle Corporation
Process CPU time: 1 hour 16 minutes
Live threads: 11
Current classes loaded: 158,679
Total classes loaded: 158,857
Total classes unloaded: 178
Current heap size: 247,097 kbytes
Maximum heap size: 253,440 kbytes
Committed memory: 253,440 kbytes
Pending finalization: {0} objects
Garbage collector:
Name = 'Copy', Collections = 28,712,
Total time spent = 5 minutes
Garbage collector:
Name = 'MarkSweepCompact', Collections = 4,464,
Total time spent = 37 minutes
Tenured Gen Used: 178,978 kbytes
Metaspace Used: 855,895 kbytes
JVM footprint: 1,168,268 K
CPU usage: 25.1%
The picture below shows you the how the JVM struggles with the Heap area for the last 50 minutes.
Conclusion: HotSpot 1.8 JVM memory management failed in this situation. It should throw an OutOfMemoryError exception, instead of spending most of the time doing garbage collection.
I guess I can let it run for another hour to see what will happen. So here is the summary of the JVM 1 hour later:
Connection name: pid: 2860 MethodAreaDynamicClass
Virtual Machine: Java HotSpot(TM) Client VM version 25.0-b70
Vendor: Oracle Corporation
Process CPU time: 2 hours 29 minutes
Live threads: 11
Current classes loaded: 170,737
Total classes loaded: 171,167
Total classes unloaded: 430
Current heap size: 244,837 kbytes
Maximum heap size: 253,440 kbytes
Committed memory: 253,440 kbytes
Pending finalization: {0} objects
Garbage collector:
Name = 'Copy', Collections = 28,712,
Total time spent = 5 minutes
Garbage collector:
Name = 'MarkSweepCompact', Collections = 11,685,
Total time spent = 1 hour 42 minutes
Metaspace Used: 937,404 kbytes
JVM footprint: 1,232,656 kbytes
CPU usage: 25.0%
Comparing with numbers collected earlier, I can see that:
I am guess is that the JVM will run out of memory on Method Area eventually. But I don't know how long it will take to get there.
Of course, if you want to see the OutOfMemoryError happening quickly, you can specify a low Method Area limit:
C:\>\progra~1\java\jdk1.8.0\bin\java -XX:MaxMetaspaceSize=256k -classpath cglib-nodep-3.1.jar;. MethodAreaDynamicClass Exception in thread "main" java.lang.OutOfMemoryError: Metaspace at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:760) at java.security.SecureClassLoader.defineClass(SecureClassLoade... at java.net.URLClassLoader.defineClass(URLClassLoader.java:455) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:367) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:360) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFact... at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultG... at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClas... at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.jav... at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:116) at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108) at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:104) at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:69) at MethodAreaDynamicClass.main(MethodAreaDynamicClass.java:12)
Last update: 2014.
Table of Contents
Downloading and Installing JDK 1.8.0 on Windows
Downloading and Installing JDK 1.7.0 on Windows
java.lang.Runtime Class - The JVM Instance
java.lang.System Class - The Operating System
ClassLoader Class - Class Loaders
Class Class - Class Reflections
JRockit JVM 28.2.7 by Oracle Corporation
Method Area Expansion Demonstration
OutOfMemoryError on the Method Area
Method Area Growth with Dynamically Generated Classes
►Garbage Collection Issue with Dynamically Generated Classes
Interned Strings Stored in Heap
Direct Memory Expansion Demonstration
allocateMemory() Method on Direct Memory
JVM Stack Expansion Demonstration
PC Register and Native Method Stack
Memory Management and Garbage Collectors
JVM Stack, Frame and Stack Overflow
Thread Testing Program and Result
CPU Impact of Multi-Thread Applications
I/O Impact of Multi-Thread Applications
Micro Benchmark Runner and JVM Options
Micro Benchmark Tests on "int" Operations
Micro Benchmark Tests on "long" Operations
Micro Benchmark Tests in JIT Compilation Mode