Home  >  Article  >  Java  >  Detailed explanation of the purpose of each area of ​​the JVM and code examples of potential exceptions

Detailed explanation of the purpose of each area of ​​the JVM and code examples of potential exceptions

黄舟
黄舟Original
2017-03-20 10:56:191983browse

Program Counter

is used for the bytecode interpreter to select the bytecode instructions that need to be executed. Each thread has an independent program counter, and the threads do not affect each other. If the thread is executing a Java method, this counter records the memory address of the virtual machine bytecode instruction being executed; if it is executing a Native method. The counter is Undefined. This area is the only area in the JVM specification where OOM does not exist

Virtual machine stack (local variable space)

stores various basic data types known to the compiler (boolean, byte, char, short, int, float, long, double), object application (reference). 64-bit double and long occupy 2 slots. The memory space can be determined during compilation. When entering a method, the local variable space that needs to be allocated by this method is completely determined. Set the memory capacity through -Xss

Exception:

StackOverflowError The stack depth is greater than the depth allowed by the virtual machine

OOM If the virtual machine stack can be dynamically expanded (most current Java virtual machines can be dynamically expanded, but the Java virtual machine specification also allows fixed-length virtual machines stack), if the extension cannot apply for enough memory

In a single thread, whether the stack frame is too large or the virtual machine stack capacity is too small, when the memory cannot be allocated, the virtual machine throws They are all StackOverflowError

/**
* VM Args:-Xss128k
* 
* stack length:2402 Exception in thread "main" java.lang.StackOverflowError
*/
public class JavaVMStackSOF {

private int stackLength = 1;

public void stackLeak() {
    stackLength++;
    stackLeak();
}

public static void main(String[] args) throws Throwable {
    JavaVMStackSOF oom = new JavaVMStackSOF();
    try {
        oom.stackLeak();
    } catch (Throwable e) {
        System.out.println("stack length:" + oom.stackLength);
        throw e;
    }
}
}

If the test is not limited to a single thread, memory overflow exceptions can be generated by continuously establishing threads. However, the memory overflow exception generated in this way has no connection with whether the space occupied is large enough. To be precise, in this case, the larger the memory allocated for each thread's stack, the easier it is to generate a memory overflow exception. .

Because the memory allocated by the operating system to each process is limited, for example, the 32-bit window is limited to 2GB. This test is done by creating a large number of threads. Each thread occupies stack memory and allocates a large amount of memory, causing the system to not have enough memory. So that it cannot be automatically expanded

/**
 * VM Args:-Xss2M (这时候不妨设大些)
 *
 * java.lang.OutOfMemoryError:unable to create new native thread
 */
public class JavaVMStackOOM {

       private void dontStop() {
              while (true) {
              }
       }

       public void stackLeakByThread() {
              while (true) {
                     Thread thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                   dontStop();
                            }
                     });
                     thread.start();
              }
       }

       public static void main(String[] args) throws Throwable {
              JavaVMStackOOM oom = new JavaVMStackOOM();
              oom.stackLeakByThread();
       }
}

Local method stack

is similar to the virtual machine stack, except that one is the virtual machine executing Java methods, and the other is executing Native methods

Exception situation:

StackOverflowError The stack depth is greater than the depth allowed by the virtual machine

OOM

Java Heap

A memory area shared by threads, from the perspective of memory recycling , basically adopt the generational collection algorithm, so it is divided into the new generation and the old generation. To be more detailed, it can be divided into Eden space, From Survivor space, To Survivor space, etc. -Xmx -Xms control heap space size

Exception situation:

1.OOM When the heap cannot be expanded

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * 
 * java.lang.OutOfMemoryError: Java heap space
 */
public class HeapOOM {

    static class OOMObject {
    }

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}

Method area

Shared between threads. Stores data such as class information, constants, static variables, code compiled by the instant editor, etc. that have been loaded by the virtual machine. It can be called the immortal generation in the HotSpot virtual machine.

Runtime constants are part of the method area in 1.6 and before (String.intern() is dynamically added to the constant pool) -XX:MaxPermSize controls the size. In JDK1.7 and later versions, it is a piece of memory developed in the Java heap

Exception situation:

OOM

/**
* 需要在JDK1.6上才能复现,JDK1.7及之后版本的JVM已经将运行时常量池从方法区中移了出来,在Java 堆(Heap)中开辟了一块区域存放运行时常量池。
* 在JDK1.7上运行的效果则会一直执行,直到堆内存使用完毕
* VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M 
*
* java.lang.OutOfMemoryError:PermGen space
*/
public class RuntimeConstantPoolOOM {

public static void main(String[] args) {
    // 使用List保持着常量池引用,避免Full GC回收常量池行为
    List<String> list = new ArrayList<String>();
    // 10MB的PermSize在integer范围内足够产生OOM了
    int i = 0;
    while (true) {
        list.add(String.valueOf(i++).intern());
    }
}
}
/**
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
* java.lang.OutOfMemoryError:PermGen space
* 一直创建动态类
*/
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 obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                return proxy.invokeSuper(obj, args);
            }
        });
        enhancer.create();
    }
}

static class OOMObject {

}
}

Direct memory (not part of the virtual machine runtime Part of the data area)

NIO can use the Native function library to directly allocate external memory, and then operate through the DirectByteBuffer object stored in the Java pair as a reference to this memory. Limited by the machine's physical memory, it can be specified by -XX:MaxDirectMemorySize. If not specified, the default is the same as the Java heap maximum value (-Xmx)

Exception:

1.OOM

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

    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
        }
    }
}

The above is the detailed content of Detailed explanation of the purpose of each area of ​​the JVM and code examples of potential exceptions. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn