jvm memory model

  For most of us java developers, jvm is something we have to understand in depth, because java development is inseparable from jvm and runs on top of java virtual machine, and in this section I will share with you jvm the memory model (i.e. the runtime data area) and the exceptions they raise when the memory overflows under certain circumstances.

1. Runtime data area

1. Program counter

  The program counter is a small memory space, which can be regarded as a line number indicator of the bytecode executed by the current thread; in order to restore the correct execution position after thread switching, each thread needs to have an independent Program counter, the counters between each thread do not affect each other and are stored independently. We call this type of memory area thread-private memory; this memory area is the only one that does not specify any **OutOfMemoryError** in the Java virtual machine specification. area

2. Java virtual machine stack

  The Java virtual machine stack is private to the thread and has the same life cycle as the thread. The virtual machine stack describes the memory model of Java method execution: each method will create a stack frame to store local variable table, operand stack, dynamic link, method exit and other information when it is executed. The process from invocation to completion of execution of each method corresponds to the process of pushing a stack frame to popping out of the stack in the virtual machine stack. If the stack depth requested by the thread is greater than the depth allowed by the virtual machine, a **StackOverflowError** exception will be thrown. If the virtual machine stack can be dynamically expanded and cannot apply for enough memory during expansion, an **OutOfMemoryError** will be thrown. The exception native method stack is very similar to the virtual machine stack. The virtual machine stack executes Java methods for the virtual machine, while the native method stack executes the native method for the virtual machine.

3. Java heap

  The Java heap is the largest piece of memory managed by the Java virtual machine. It is a memory area shared by all threads and is created when the virtual machine starts. The only purpose of this memory area is to store object instances. Almost all object instances allocate memory here. It is also the main area managed by the garbage collector. It is called the "GC heap". If there is no memory in the heap to complete the instance allocation, and When the heap can no longer be expanded, an "**OutOfMemoryError**" exception will be thrown.
In order to enable the JVM to better manage the objects in the heap memory, including memory allocation and recycling, the heap is divided into two different areas. : **New generation**, **Old generation**, the default ratio is 1:2 (you can pass -XX:NewRatio), and the new generation can be divided into three areas **Eden**, **From Survivor **, **To Survivor**, the default ratio is 8:1:1 (can be set by -XX:SurvivorRatio, for example =3 is 3:1:1)

4. Method area

  The method area (permanent generation) is a memory area shared by each thread , which is used to store data such as class information, constants, static variables, and code compiled by the just-in-time compiler that have been loaded by the virtual machine. When the method area cannot meet the memory allocation requirements, an **OutOfMemoryError** exception will be thrown

5. Runtime constant pool

  The runtime constant pool is a part of the method area. In addition to the description information of the class version, field, method, interface, etc., there is also a constant pool in the Class file, which is used to store various literals and symbolic references generated during compilation. , this part of the content will be stored in the runtime constant pool of the method area after the class is loaded. Thread sharing , when the constant pool can no longer apply for memory, an **OutOfMemoryError** exception will be thrown

2. Exceptions generated by each data area

1. java heap overflow

  The java heap is used to store object instances. As long as objects are constantly created and there is a reachable path between GC Roots and objects to avoid garbage collection mechanism clearing these objects, memory overflow will occur when the number of objects reaches the limit of the maximum heap. Exception
The following code limits the size of the java heap to 20MB, which is not expandable (set the minimum value -Xms parameter of the heap and the maximum value -Xmm parameter to be the same to avoid automatic heap expansion), through -XX:+HeapDumpOnOutOfMemoryError can make the virtual machine Dump out the current memory heap dump snapshot when a memory overflow exception occurs so that it can be analyzed at a later time

// -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
public class HeapOOM {
  static class OOMObject{
  }
  public static void main(String[] args) {
    List<OOMObject> list=new ArrayList<OOMObject>();
    while(true){
    list.add(new OOMObject());
    System.out.println("------");
    }
  }
}

打印异常:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid14612.hprof ...
Heap dump file created [19332773 bytes in 0.186 secs]


2. Virtual machine stack overflow

  The stack memory capacity can be set by the -Xss parameter.
  In single-threaded operation, whether the stack frame is too large or the virtual machine stack frame capacity is too small, when the memory cannot be allocated, the virtual machine throws a StackOverflowError exception.

// -Xss128k
public class JavaVMStackSOF {
  private int stackLength=1;
  public void stackLeak(){
  stackLength++;
  System.out.println("___---___---");
  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;
    }
  }
}

Print exception:
Exception in thread "main" java.lang.StackOverflowError
___---____---stack length: 955

If the test is not limited to a single thread, a memory overflow exception can be generated by continuously creating threads

public class JavaVMStackSOF {
    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) {
        JavaVMStackSOF oom=new JavaVMStackSOF();
        oom.stackLeakByThread();
} 

Explanation:
An OutOfMemoryError exception will be thrown at this time

3. Method area and runtime constant pool overflow         

  String.intern() is a Native method. Its function is: if the string constant pool already contains a string equal to this String object, it returns a String object representing the string in the pool; otherwise, this String object is returned. The contained string is added to the constant pool, and a reference to this String object is returned. In JDK1.6 and earlier versions, since the constant pool is allocated in the permanent generation, we can limit the size of the method area by -XX:PremSize and -XX:MaxPermSize, thereby indirectly limiting the capacity of the constant pool,

List<String> list=new ArrayList<String>();
int i =0;
while(true){
list.add(String.valueOf(i++).intern());}

At this point, OutOfMemoryError: PerGen space will be thrown


JDK1.7 will not get the same result, the while() loop will continue to go on, because JDK1.7 begins to gradually "de-permanent generation"

4. Different jdk versions have different results

Execute the following code (jdk1.6, jdk1.7)

String str1=new StringBuilder("Computer").append("Software").toString();
System.out.printIn(str1.intern() == str1);
String str2=new StringBuilder("ja").append("va").toString();
System.out.printIn(str2.intern() == str2);

Detailed explanation:
  When this code runs in JDK1.6, it will get two false, while in JDK1.7, it will get one true and false. In JDK1.6, the intern() method will put the string encountered for the first time The instance is copied to the permanent generation, and the reference to the string instance in the permanent generation is also returned, and the string instance created by StringBuilder is on the Java heap, so it must not be the same reference, it will return false, and the intern of JDK1.7 () implementation will not copy the instance, but only record the first occurrence of the instance reference in the constant pool, so the reference returned by intern() is the same as the string instance created by StringBuilder. The comparison of str2 returns false because the string "java" has appeared before StringBuilder.toString(), and
there is already a reference to it in the string constant pool, which does not conform to the principle of "first appearance", and "computer software" This string is the first occurrence, so it returns true

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324841717&siteId=291194637