Metaspace is out of memory

The Metaspace area rarely runs out of memory, and when it does, it usually does so for two reasons:

  • If you don’t understand how the JVM works, you will use the default Metaspace area when you launch the system. This will result in the default Metaspace area being only a few tens of MEgabytes. In this case, for a slightly larger system, because there are many classes and many external JARS, there are many classes. A few dozen Megabytes of Metaspace can easily become inadequate
  • Using a technique like Cglib to generate classes on the fly makes it easy to overstuff Metaspace and run out of memory if you don’t have the right controls in your code to generate too many classes

Simulation case

Maven is introduced into

<dependency>
 <groupId>cglib</groupId>
 <artifactId>cglib</artifactId>
 <version>3.3.0</version>
</dependency>
Copy the code

Java code

public class Demo3 {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Test.class);
        enhancer.setUseCache(false);
        enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
            if (method.getName().equals("run")) {
                System.out.println("Reflection execution");
            }
            return method.invoke(o, objects);
        });
        Test test = (Test) enhancer.create();
        test.run();
    }

    static class Test {
        public void run(a) {
            System.out.println("Test code..."); }}}Copy the code

Caused by: java.lang.OutOfMemoryError: Metaspace

Stack overflow

If thread calls the method constantly, constantly in the stack frame on the stack, there will come a moment at this time, a lot of stack frame will be depleted the 1 MB of thread stack memory, will eventually lead to a stack of memory, in general, actually trigger a stack of memory, often wrote some bug in the code would lead to, under normal circumstances happen less

Simulation case

public class Demo4 { public static void main(String[] args) { test(); } public static void test(){ test(); }}Copy the code

Exception in thread “main” java.lang.StackOverflowError at com.silly.demo.jvm.Demo4.test(Demo4.java:12)

Heap overflow

There are too many objects in the limited memory, and most of them are still alive, even after GC, so it is impossible to put more objects in, which can only cause an overflow problem. So in general there are two main scenarios for memory overflow:

  • The system bears a high number of concurrent requests. As a result, a large number of objects are alive, so it is impossible to add new objects. In this case, OOM system crashes
  • The system has a memory leak, which is a problem where there are a lot of objects that are alive and not referenced in time, causing GC to trigger and fail to collect, and causing a memory leak because there is no room for any more objects

In summary, OOM is usually caused by high system load or memory leak

This OOM problem, once your code is not very good, or design defects, or relatively easy to cause, so this problem is we will focus on the later analysis.

Simulation case

public class Demo5 { public static void main(String[] args) { List<Object> list = new ArrayList<>(); while (true) { list.add(new Object()); }}}Copy the code

Exception in thread “main” java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:265) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231) at java.util.ArrayList.add(ArrayList.java:462) at com.silly.demo.jvm.Demo5.main(Demo5.java:14)

In OOM, memory snapshots are automatically dumped

We can have it dump a snapshot of memory in OOM, and then we can analyze the snapshot and see which objects are occupying all the memory

Save, and can not be released. In this case, you need to add the following parameters to the JVM startup parameters:

-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/usr/local/app/oom
Copy the code