java.lang.OutOfMemoryError: Metaspace
Environment
- OpenJDK 1.8
- Oracle JDK 1.8
- JBoss Enterprise Application Platform (EAP)
- 6.4.x
- 7.x
Issue
java.lang.OutOfMemoryError: Metaspace
Resolution
-
Increase the size of the Metaspace using the
-XX:MaxMetaspaceSize
argument. For example:-XX:MaxMetaspaceSize=2g
-
When
UseCompressedOops
andUseCompressedClassesPointers
are enabled (default), increase the size of the class metadata space. the following options will result in a 2g space for class metadata and 1g space for compressed class pointers:-XX:MetaspaceSize=2g -XX:MaxMetaspaceSize=2g -XX:CompressedClassSpaceSize=1g
-
See "Metadata GC Threshold" garbage collections are not able to free space.
- See JDK 8 Metaspace tuning for JBoss EAP .
Root Cause
- The Metaspace is being exhausted. Either it is undersized, or there is a leak.
- The Perm Gen space has been removed in JDK8 and replaced by the Metaspace. Class metadata previously stored in the Perm Gen space is now allocated in the Metaspace in native memory. By default the class metadata allocation is only limited by 32/64 bit addressable memory. The new flag
-XX:MaxMetaspaceSize
argument can be used to limit the amount of native memory used. - Garbage collection of dead classes and classloaders is triggered when class metadata usage reaches
MetaspaceSize
. An undersized Metaspace can cause poor performance due to excessive garbage collection. - The application has many classes (e.g. many JSPs).
- There are many static member variables in classes.
- There is heavy use of String.intern().
- There is a classloader leak. If an object outside the classloader holds a reference to an object loaded by the classloader, the classloader cannot be collected.
- There are many isolated classloaders.
- The CMS low pause collector by default does not collect the permanent generation space.
- Hot deployment or redeployment is exposing a classloader leak.
- Hot Deployment Exhausts the PermGen when the Application Uses Ehcache
- Hot Deployment Exhausts the PermGen when the Application Includes Database Drivers
- Spring proxy cache causes PermGen OOME across redeployments
- JBoss application classloaders leak because of unclosed EJBReceiverContexts and EJBClientContexts
- Application with log4j causes perm gen leak across redeployments
- Singleton patterns where a class has a static reference to the class itself, making the class unloadable.
- Heavy use of dynamic proxies.
- JON Agent is failing with error OutOfMemoryError: PermGen space or Java heap space
- AOPClassProxy exhausts PermGen
- Domain controller and host controller lose connection due to 'OutOfMemoryError: PermGen space'
- java.lang.OutOfMemoryError: PermGen when using groovy script in camel
- Perm or Metaspace OOME due to many duplicate JaxbAccessor classes
- Permgen or Metaspace leak at org.apache.cxf.common.util.ProxyClassLoader in JBoss EAP 6.4 CP04/CP05
- Redeploying switchyard app results in OOME
- Perm or Metaspace OOME due to classloaders persisted by ClassLoaderLogContextSelector
- Aborted transactions not being cleared causing memory leak
Diagnostic Steps
Server Log Analysis
Verify the OOME is due to Metaspace.
GC Log Analysis
Verify a full collection does not reclaim Metaspace.
Classloader Stats Analysis
JDK8 u13+
-
Enable
-XX:+UnlockDiagnosticVMOptions
then captureGC.class_stats
withjcmd
(JDK 1.8 u13+):$JAVA_HOME/bin/jcmd <JBOSS_JAVA_PID> GC.class_stats -all -csv > class_stats.csv
Notes:
- Forces a full gc.
- Open
class_stats.csv
in a spreadsheet (e.g. LibreOffice Calc). - Check
InstBytes
column for largest retainers. - Review the largest retainers in the heap dump to look for clues. See below.
JDK 1.8 u13-
-
Get
clstats
output from a time of high Metaspace piped to a file:$JAVA_HOME/bin/jmap -clstats <JAVA_PID> > clstats.out
Example output:
Attaching to process ID 12345, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.101-b13 class_loader classes bytes parent_loader alive? type <bootstrap> 2631 4705272 null live <internal> 0x00000000c91be518 1 1455 0x00000000fdcf0978 dead sun/reflect/DelegatingClassLoader@0x00000001000099d8 0x00000000c377a770 0 0 0x00000000fd618000 live org/eclipse/osgi/internal/loader/EquinoxClassLoader@0x00000001000bf438 0x00000000c64f4a48 454 772114 0x00000000fd618000 live org/eclipse/osgi/internal/loader/EquinoxClassLoader@0x00000001000bf438 ... 0x00000000c7651c90 1 864 0x00000000c35c1d98 dead sun/reflect/DelegatingClassLoader@0x00000001000099d8 0x00000000c2ff5108 54 136855 0x00000000fd618000 live org/eclipse/osgi/internal/loader/EquinoxClassLoader@0x00000001000bf438 0x00000000c76f9898 1 1455 0x00000000c3eb0f60 dead sun/reflect/DelegatingClassLoader@0x00000001000099d8 total = 426 31560 64301535 N/A alive=277, dead=149 N/A
Notes:
- Do not use this for JDK 1.8 u13+. It does not seem to provide useful information.
- Requires debuginfo.
- Requires running
jmap
as the user that started the Java process. - Will put the JVM in a safepoint (all threads stopped) while running.
- Make take several minutes to produce output.
- Forces a full gc.
Heap Dump Analysis
Get a heap dump when OOME happens using the -XX:+HeapDumpOnOutOfMemoryError
option and check the following:
-
Use the following Object Query Language (OQL) query to find duplicate deployments (e.g. duplicate application war/ear/jars):
#EAP6 SELECT module.identifier.name.value.toString() FROM org.jboss.modules.ModuleClassLoader #EAP7 SELECT module.name.value.toString() FROM org.jboss.modules.ModuleClassLoader
-
Check for multiple instances of
org.apache.cxf.common.jaxb.JAXBContextCache$2
. - Review the classes that classloader stats analysis showed are the largest retainers for clues. For example, what are the immediate dominators? What are the GC root(s)?
- Check the stack traces of running threads and review for patterns.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
1 Comments
In our environment the metaspace problem could be solved by changing the undertow configuration. We changed jsp-config development back to "false" (default). With "true" metaspace is growing permanently. <websockets/> Perhaps this helps as another possible solution.