Enjoy Sharing Technology!

Software,Develope,Devops, Security,TroubleShooting

Wednesday, November 17, 2021

OutOfMemoryError(4): Metaspace

A series of articles on this topic:

JVM limits the maximum memory of Java programs, and this limitation can be changed by modifying/specifying startup parameters. Java divides the heap memory into multiple parts, as shown in the following figure:


[Java8 and above] The maximum value of these memory pools is specified by JVM startup parameters such as -Xmx and -XX:MaxMetaspaceSize. If not explicitly specified, it will be determined according to the platform type (OS version + JVM version) and the size of the physical memory. java.lang.OutOfMemoryError: The information expressed by the Metaspace error is: Metaspace has been used up.

Cause Analysis
If you are an old Java driver, you should be familiar with PermGen. But starting from Java 8, the memory structure has undergone major changes. Permgen is no longer used, but a new space is introduced: Metaspace. This change is based on many considerations, partly The reasons are listed as follows:

The specific size of the Permgen space is difficult to predict. Specifying a small size will cause java.lang.OutOfMemoryError: Permgen size error, and setting too many will cause waste.

In order to improve the performance of GC, the concurrent phase of the garbage collection process is no longer paused, and metadata is specifically traversed (specific iterators).

Deeply optimize the concurrent class unloading of the G1 garbage collector.

In Java 8, all the content in PermGen before has been moved to the Metaspace space. For example: class name, field, method, bytecode, constant pool, JIT optimized code, etc.

Metaspace usage is related to the number/size of classes loaded into memory by JVM. It can be said that the main reason for java.lang.OutOfMemoryError: Metaspace error is that the number of classes loaded into the memory is too large or the size is too large.

Example
Similar to PermGen , the amount of Metaspace space used has a lot to do with the number of classes loaded by the JVM. Here is a simple example:

public class Metaspace {
  static javassist.ClassPool cp = javassist.ClassPool.getDefault();
  public static void main(String[] args) throws Exception{
    for (int i = 0; ; i++) { 
      Class c = cp.makeClass("eu.plumbr.demo.Generated" + i).toClass();
    }
  }
}

As you can see, it is very simple to use the javassist tool library to generate a class. In the for loop, a lot of classes are dynamically generated, and these classes are finally loaded into the Metaspace.

Execute this code, as more and more classes are generated, it will eventually fill up the Metaspace space, throwing java.lang.OutOfMemoryError: Metaspace. On Mac OS X, in the Java 1.8.0_05 environment, if the startup is set Parameter -XX:MaxMetaspaceSize=64m, JVM will hang after about 70,000 classes are loaded.

solution:

If an OutOfMemoryError related to Metaspace is thrown, the first solution is to increase the size of Metaspace. Use the following startup parameters:

-XX:MaxMetaspaceSize=512m

Here, the maximum value of Metaspace is set to 512MB, if it is not used up, OutOfMemoryError will not be thrown.

There is a seemingly simple solution, which is to directly remove the size limit of Metaspace. But it should be noted that there is no limit to the size of Metaspace memory. If the physical memory is insufficient, it may cause memory swapping, which will seriously affect system performance. In addition, it may cause problems such as native memory allocation failure.

In modern application clusters, it is better to let the application node go down than to respond slowly.

If you don't want to receive an alarm, you can hide the java.lang.OutOfMemoryError: Metaspace error message like an ostrich. But this will not really solve the problem, it will only delay the outbreak of the problem. If there is a memory leak, please refer to these articles and look for a solution carefully.
Share:

1 comment:

Search This Blog

Weekly Pageviews

Translate

Blog Archive