JVM virtual machine (3): Java memory area and memory overflow exception

Runtime data area

  When the Java virtual machine executes the Java program, it will divide the memory it manages into several data areas with different division of labor.

Runtime data area

Program counter

  The program counter is a small memory space, which can be regarded as the line number indicator of the bytecode executed by the current thread. Basic operations such as branching, looping, jumping, exception handling, and thread recovery all need to rely on it to complete. In order to ensure that the thread can be restored to the correct execution position, each thread needs an independent program counter every day. The counters of each thread do not affect each other and are stored independently. This type of memory area is "thread-private" memory, and there is no GC or OOM in this area.

Java Virtual Machine Stack

  Like the program counter, the Java virtual machine stack is also private to the thread, and its life cycle is the same as the thread. When each method is executed, the Java virtual machine will synchronously create a stack frame for storing local variable table, operand stack, dynamic link, method exit and other information. After the method is executed, the stack frame is ejected from the virtual machine stack.

  The local variable table stores various basic data types (boolean, byte, char, short, int, float, long, double) and object references (reference type, which are not equivalent to the object itself, may be known at compile time. It is a reference pointer of the starting address of the execution object, it may also point to a handle representing the object or other object-related location) and returnAddress type (pointing to the address of a bytecode instruction). These data types are stored as local variable slots in the local variable table storage space, where double and long types will occupy two variable slots, and the remaining data types only occupy one. There is no GC and OOM in this area.

Native method stack

  The role of the local method stack and the virtual machine stack is very similar. The only difference is that the virtual machine stack executes Java method services for the virtual machine, while the local method stack uses the local method services for the virtual machine.

Java heap

  The Java heap is an area shared by all threads and is created when the virtual machine is started. Almost all object instances and arrays should be allocated on the heap. The Java heap shared by all threads can be divided into multiple private allocation buffers of threads to improve the efficiency of object allocation. It can be realized in the size of a vault, or it can be extended (set by -Xmx and -Xms). If there is no memory in the Java heap to complete the power allocation, and the heap can no longer be expanded, the Java virtual machine will throw OOM.

Method area

  The method area, like the Java heap, is a memory area shared by threads. It is used to store type information, constants, static variables, and code cache data compiled by the real-time compiler that have been loaded by the virtual machine. Before JDK 1.8, the method area was placed in the permanent generation of the Java heap. Since JDK1.8, the method area has been transferred to the metaspace. If the method area cannot meet the new memory allocation requirements, OOM will be thrown.

Runtime constant pool

  The runtime constant pool is part of the method area. The constant pool after the Class file is compiled is used to store various literals and symbol 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. The runtime constant pool has another important feature compared to the Class file constant pool, which is dynamic, that is, new constants can also be put into the constant pool during runtime. OOM will be thrown when the constant pool can no longer apply for memory.

Object exploration

Object creation

  When the Java virtual machine encounters a bytecode new instruction, it will first check whether the parameter of this instruction has a symbolic reference of the class in the constant pool, before checking whether the class represented by this symbolic reference has been loaded, resolved, and initialized. If the corresponding class loading process is not performed first. After the class loading check is passed, allocate memory for the newborn object. The memory size of the object can be completely determined after the loading is completed, and a corresponding size of memory space is divided in the heap memory.

  Assuming that the memory in the Java heap is absolutely regular, all used memory is placed on one side, free memory is placed on the other side, and a pointer is placed in the middle as an indicator of the demarcation point, then allocating memory is to point the pointer to the free space Move a distance equal to the size of the object, this allocation method is called "pointer collision".

  The memory in the Java team is not regular. The used and free memory are interleaved with each other. At this time, the virtual machine must maintain a list to record which memory is available. When allocating, find a large enough space from the list. Assign to objects and update the records on the list. This allocation method is called "free list".

  There are two solutions to the thread safety problem: one is to synchronize the actions of allocating memory space-in fact, the virtual machine uses CAS with failed retry to ensure the atomicity of the update operation; the other is to use memory The allocation operation is performed in different spaces according to the thread division, that is, each thread is pre-allocated a small piece of memory in the java heap, called local thread buffer (Thread Local Allocation Buffer, TLAB), which thread should allocate memory, In which thread's local buffer is allocated, only when the local buffer is used up, a synchronization lock is required when allocating a new buffer. Whether the virtual machine uses TLAB can be set with the -XX: +/- UseTLAB parameter.

Object memory layout

  The storage layout of objects in the heap memory can be divided into three parts: the header, the instance data and the padding.

  • Object header: The object header contains two parts. The first part is used to store the runtime data of the object itself, such as hash code, GC generation age, lock status flag, lock held by the thread, biased thread ID, biased time stamp, etc. The second part is the type pointer, that is, the pointer of the object to its type metadata. The JVM uses this pointer to determine which class of the object is an instance.
  • Instance data: store the real effective information of the object, that is, the contents of various types of fields defined in the program code.
  • Alignment padding: No special meaning, it only serves as a placeholder.

Object access positioning

  There are two main access methods for object references: using handles and direct pointers:

  • If you use handle access, the Java heap may be divided into a memory as a handle pool, the reference is stored in the handle address of the object, and the handle contains the specific address information of the object instance data and type data.
  • If you use direct pointer access, the memory layout of the object in the Java heap must consider how to prevent access to relevant information of type data. The reference stores the object address directly. If you only access the object itself, you do not need to access it once more Overhead.

Guess you like

Origin www.cnblogs.com/chinda/p/12721562.html