The foreword 0.

Version: JDK7

1. Run time data area

1.1 Program counter

  • Small memory space, line number indicator of bytecode being executed by the current thread
  • The thread executes a Java method that records the address of the virtual machine bytecode instruction being executed
  • Thread executes Native method, record null (Undefined)
  • The only area that does not specify OOM status

1.2 VM Stack (Java Stack)

  • Describes an in-memory model for Java method execution
  • Each method execution creates a stack frame, which stores information about local variables, operand stacks, dynamic links, method exits, and so on
    • Incoming method frame into the stack, leaving method frame out of the stack
    • Local variable tables store basic data types (byte, short, int, long, float, double, char, Boolean), object references (reference type, A reference pointer to the starting address of the object, to the address of the handle representing the object, to other object related locations), the returnAddress type (to the address of the bytecode instruction)
    • Local variable table memory size is determined at compile time and does not change at run time
  • Thread request stack depth greater than the allowed depth of the VM, SOF exception was raised
  • Unable to allocate enough memory during stack expansion, an OOM exception is raised

1.3 Local method stack

  • Similar to the virtual machine stack, serving Native methods
  • The language, mode, and data structure used by methods in the local method stack are not mandatory, and can be implemented by different VMS
  • For example, the SOF and OOM exceptions can be thrown in the VM stack

1.4 the heap

  • The area with the largest memory in most VMS is created when the VM starts
  • Almost all object instances allocate memory here
  • The area that the garbage collector primarily manages
  • You can be in a physically discontinuous memory space as long as it is logically contiguous
  • An OOM exception is raised because there is no memory space allocated for the object instance

1.5 method area

  • Store virtual machine-loaded class information, constants, static variables, code compiled by the just-in-time compiler, and other data
  • The HotSpot VIRTUAL machine implements this zone using persistent generation, but still requires the garbage manager to reclaim memory, which is very demanding
  • You can be in a physically discontinuous memory space, and you can choose not to implement garbage collection
  • Symptom An OOM exception is raised when the memory cannot be allocated

1.6 Runtime constant pool

  • Stores literal and symbolic references generated at compile time

    • Literals: string text, values for the eight basic data types, constants declared final
    • Symbolic references: fully qualified names of classes and interfaces, field names and descriptors, method names and descriptors
  • New constants can be placed in this area at run time

  • Symptom An OOM exception is raised when the memory cannot be allocated

1.7 String Constant Pool

  • Stores non-repeating strings
  • String str = "hello";String constant pool returns references to variables if “hello” exists, and creates and returns references to variables if not
  • String str = new String("hello");String constant pool not created if “hello” exists, create one if it does not exist; The new keyword also creates an object instance in the heap and returns a reference to the variable

2. HotSpot VIRTUAL machine object

2.1 Object Creation

Class load -> Allocate memory space -> initialize memory space with zero values (excluding object headers) -> Set object information (such as object headers) -> execute init method and initialize as desired by programmer

2.1.1 Memory Allocation Mode

Whether or not the garbage collector of the heap has a collation function determines whether or not the memory is orderly, and whether or not the memory is orderly determines how to allocate

  • Pointer collision: If memory in the heap is orderly, allocated and unallocated areas are set aside, with a pointer in the middle as an indicator of the cut-off point. When allocating memory for an object, a pointer moves the object’s memory an equal distance to the unallocated area

  • Free list: If the memory in the heap is not tidy and allocated and unallocated areas are interlaced, the virtual machine needs to maintain a list of which memory areas are available. When allocating memory for an object, find an available area from the list and update the records on the list

2.1.2 Thread safety During Memory Allocation

Thread safety problems occur when VMS frequently allocate memory because the heap is shared by threads. The solution is as follows:

  • If the CAS fails, try again to ensure atomicity of the operation

  • Local Thread allocation buffer (TLAB) : Each thread preallocates an area in the heap, and each thread allocates memory in its own area. Lock synchronously only when the TLAB runs out and new tLabs need to be allocated (can be set with -xx :+/ -usetlab parameter)

2.2 Object Memory Layout

  • Object:
    • Mark Word:
      • Store object runtime data such as hash code, GC generation age, lock status flag, thread holding lock, bias thread ID, bias timestamp, and so on
      • Non-fixed data structures to store more information in a very small space
    • Type pointer:
      • A pointer to the class metadata of the object that the VM can use to determine which class instance the object belongs to
    • Array length:
      • When an array object, records the length of the array
  • Instance data:
    • Store actual valid information about an object
    • The storage order is affected by the order in which the VM allocation policy and fields are defined in the Java source code
  • Align fill:
    • A placeholder to ensure that the object is a multiple of 8 bytes

2.3 Object Access positioning

When objects are needed, specific objects in the heap can be manipulated using reference data in the stack. Reference data stores a reference to an object. There are two main ways to access an object by reference: handle and direct pointer

  • Using handles: The heap divides an area as a handle pool, and reference in the stack stores the address of the object handle, which contains the specific address of the instance data and type data of the object

  • Direct pointer: The reference in the stack stores the address of the object in the heap. The layout of the object in the heap holds the specific address of the object’s instance data and type data

Both approaches have their own advantages:

  • Use handles: The address of the object’s handle stored in the stack is stable, and only the instance data pointer in the handle is changed when the object is moved (a common behavior in garbage collection)
  • Direct use: The access speed is fast and the time cost of locating Pointers is saved. The HotSpot VM uses this method

3. Data area memory overflow

3.1 the heap overflow

The heap fails to allocate memory for the object, causing an OOM exception

/** * VM Args: - Xms20m - Xmx20m - XX: + HeapDumpOnOutOfMemoryError * - Xms heap memory initial value * -xmx maximum heap memory * - XX: + HeapDumpOnOutOfMemoryError memory dump A snapshot of the current memory heap dump is displayed for subsequent analysis
public class HeapOOM {

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

        while (true) {
            list.add(newOOMObject()); }}}Copy the code

Online tool to analyze memory heap dump snapshots: PerfMa

3.2 stack overflow

Recursively call method to add stack frame, stack cannot allocate memory to stack frame throw SOF exception

/** * VM Args: -xss256K ** -xSS stack memory size */
public class StackSOF1 {

    private int stackLength = 1;

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

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

An OOM exception occurs because the memory in the process cannot be allocated to the stack memory due to an increasing number of threads obtaining stack memory. Procedure

* VM Args: -xSS50M ** -xSS stack memory size */
public class StackOOM {

    private void dontStop(a) {
        while (true) {}}public void stackLeakByThread(a) {
        while (true) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run(a) { dontStop(); }}); thread.start(); }}public static void main(String[] args) throws Throwable {
        StackOOM oom = newStackOOM(); oom.stackLeakByThread(); }}Copy the code

3.3 Method area overflow

Cglib keeps creating proxy classes, methods cannot allocate memory for class information and raises an OOM exception

/** * VM Args: -xx :PermSize=2M -xx :MaxPermSize=2M ** -xx :PermSize Initial value of the persistent memory * -xx :MaxPermSize Maximum value of the persistent memory */
public class MethodAreaOOM {

    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 {
                    returnproxy.invokeSuper(obj, args); }}); enhancer.create(); }}static class OOMObject {}}Copy the code

3.4 Direct Memory Overflow

Unsafe. AllocateMemory () requests memory, direct memory cannot allocateMemory and raises an OOM exception

/** * VM Args: -xx :MaxDirectMemorySize=200M ** -xx :MaxDirectMemorySize Specifies the maximum direct memory size */
public class DirectMemoryOOM {

    private static final int _100MB = 1024 * 1024 * 100;

    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(_100MB); }}}Copy the code

From Understanding the Java Virtual Machine in Depth (2nd edition)