JVM memory overflow test

    I am a beginner in java. I saw that the interviewer asked a lot of questions about JVM, so I learned a little bit and shared it with you. I hope you will point out any mistakes.
    To solve the problem of memory overflow, we say why memory overflows. Running a large software or game requires far more memory space than the memory installed in your host can withstand, which is called memory overflow.
    For a virtual machine, the JVM includes a set of registers, a stack, a garbage collection heap, and a storage method field. Our instance objects will be placed in the java heap space, ordinary objects will be stored in the stack, as well as the method area, constant pool, etc., as well as native memory, so for the problem of memory overflow, we already have a clue where to find the culprit .
A: The java heap overflows
The java heap is used to store our instance objects. When we keep creating objects, we keep holding references to objects to prevent them from being gc.
The test is as follows:
[img]package demo;

import java.util.ArrayList;
import java.util.List;

/**
* VM Args:-verbose:gc -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
* */
public class HeapOverFlow {
public static void main(String[] args) {
List<HeapOverFlow> hofs=new ArrayList<HeapOverFlow>();
while(true){
hofs.add(new HeapOverFlow());
}
}
}
[/img]

设置xms为20m,xmx为20m,执行效果如下:

[img]
[GC 17190K->17190K(20352K), 0.0071101 secs]
[GC 18470K->18469K(20352K), 0.0078375 secs]
[GC 18573K->18558K(20352K), 0.0011519 secs]
[Full GC 18558K->18558K(20352K), 0.0546033 secs]
[Full GC 18558K->17808K(20352K), 0.0763401 secs]
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid4784.hprof ...
Heap dump file created [32577359 bytes in 0.842 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2760)
at java.util.Arrays.copyOf(Arrays.java:2734)
at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
at java.util.ArrayList.add(ArrayList.java:351)
at demo.HeapOverFlow.main(HeapOverFlow.java:13)

[/img]
This happens The situation depends on whether it is a memory leak or a memory overflow. If there is a memory leak, you need to find the leak point. If it is a memory overflow, you need to increase the memory space. As for how to do it, there is no research yet.

B: Virtual machine stack and local method stack overflow

Since the virtual machine stack and the local method area stack are not distinguished in the HotSpot virtual machine, for HotSpot, the -Xoss (set local method stack size) parameter is invalid, and the stack capacity Set by the -Xss parameter. Regarding the virtual machine stack and the native method area stack, two exceptions are described in the Java Virtual Machine Specification:
If the stack depth requested by the thread is greater than the maximum depth allowed by the virtual machine, a StackOverflowError exception will be thrown
If the virtual machine cannot expand the stack If enough memory space is applied for, an OutOfMemoryError exception will be thrown.

In the book "Introduction to Java Virtual Machine", only StackOverflowError can appear in the single-threaded scenario. Then let's take a look at what it will look like in the single-threaded scenario. .

[img]public class StackOverFlow {
private int stackLength = 1;
  private void stackLeak() {
    stackLength++;
    stackLeak();
  }
 
  public static void main(String[] args) throws Throwable {
  StackOverFlow oom = new StackOverFlow();
    try {
      oom.stackLeak();
    } catch (Throwable e) {
      System.out.println("stack length :" + oom.stackLength);
      throw e;
    }
  }
  }[/img]
Set -Xss128k The result is as follows:

[img]stack length:2402
Exception in thread "main" java.lang.StackOverflowError
at demo.StackOverFlow.stackLeak( StackOverFlow.java:11)
at demo.StackOverFlow.stackLeak(StackOverFlow.java:12)[/img]

By continuously creating threads to exhaust memory, OutOfMemoryError can also be displayed. Since it will cause a crash under Windows, I will not try it here. .

C: Runtime constant pool overflow

The easiest way to add something to the runtime constant pool is to use the String.intern() method. Since the constant pool is allocated in the method area, you can limit the size of the method area through -XX:PermSize and -XX:MaxPermSize, thereby indirectly limiting the capacity of the constant pool.

Example:
import java.util.ArrayList;
import java.util.List;

/**
* VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
* @author Administrator
*
*/
public class StaticConstantPoolOF {
public static void main (String[] args) {

      List<String> list = new ArrayList<String>();

      int i = 0;

      while (true) {
        list.add(String.valueOf(i++).intern());
      }
    }
}

The running result is as follows:
[img][GC 3159K->2263K(5056K), 0.0005486 secs]
[Full GC 2403K->1018K(5056K), 0.0387303 secs]
[Full GC 1018K->1018K(5056K), 0.0416562 secs]
[Full GC 1033K->242K(5056K), 0.0150953 secs]
Exception in thread "main" java. lang.OutOfMemoryError: PermGen space
at java.lang.String.intern(Native Method)
at demo.StaticConstantPoolOF.main(StaticConstantPoolOF.java:24)[/img]

D: The method area overflows

The method area is used to store the relevant information of the Class, Such as class name, access modifier, constant pool, field description, method description, etc. Test this area as long as a large number of classes fill up the method area at runtime, until the overflow. "In-depth understanding of Java virtual machine" uses CGlib to directly manipulate the bytecode runtime, and generate a large number of dynamic classes.

The current mainstream Spring and Hibernate will use bytecode technologies such as CGLib when enhancing classes. The more classes are enhanced, the larger the method area is required to ensure that dynamically generated classes can be loaded into memory.
[img]import net.sf.cglib.proxy.Enhancer;
  import net.sf.cglib.proxy.MethodInterceptor;
  import net.sf.cglib.proxy.MethodProxy;

  /**
   * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
   *
   */
  public class JavaMethodAreaOOM {
    public static void main(String[] args) {
      while (true) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(OOMObject.class);
        enhancer.setUseCache(false);
        enhancer.setCallback(new MethodInterceptor() {
          public Object intercept(Object object, Method method,
              Object[] args, MethodProxy proxy) throws Throwable{
            return proxy.invokeSuper(object, args);
          }
        });
        enhancer.create();
      }

    }

    static class OOMObject {

    }

  }[/img]

The project should introduce cglib-2.2.2.jar and asm-all-3.3.jar.
The memory overflow problem of the method area also has the difference between the jdk6 and jdk7 versions, and the memory overflow of the constant pool at runtime.
Method area overflow is also a common memory overflow exception. If a class is to be reclaimed by the garbage collector, the judgment conditions are very harsh. In applications that often generate a large number of classes dynamically, special attention should be paid to the recycling status of classes. In addition to the above-mentioned programs that use CGLib bytecode enhancement, such scenarios are common: a large number of JSPs or applications that dynamically generate JSP files, OSGi-based applications, etc.

E: The direct memory

capacity of the machine's direct memory overflow can be specified by -XX:MaxDirectMemorySize.

  import java.lang.reflect.Field;
  import sun.misc.Unsafe;

  /**
   * VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
   *
   */
  public class DirectMemoryOOM {

    private static final int _1MB = 1024 * 1024;

    /* *
     * @param args
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    public static void main(String[] args) throws IllegalArgumentException,
        IllegalAccessException {
      // TODO Auto-generated method stub
      Field unsafeField = Unsafe.class.getDeclaredFields()[0];
      unsafeField.setAccessible(true);
      Unsafe unsafe = (Unsafe) unsafeField.get(null);
     
      while(true){
        unsafe.allocateMemory(_1MB);
      }
    }

  }
该例子还没测试。

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326828138&siteId=291194637