JVM---Instantiated memory layout and access location of objects

Object instantiation memory layout and access location

Interview questions

  1. How are objects stored in the JVM?
  2. What's in the object header information?
  3. What's in the Java object header?

Start with the method and steps of object creation:
Insert picture description here

The way the object is created

  • new: The most common way to call the static class method of getInstance in the singleton class, the static method of XXXFactory;
  • Class's newInstance method: a method marked as obsolete in JDK9, because it can only call the empty parameter constructor;
  • Constructor's newInstance(XXX): reflection method, you can call the constructor with empty or with parameters;
  • Use clone(): Do not call any constructor, and require the current class to implement the clone interface in the Cloneable interface;
  • Use serialization: serialization is generally used for Socket network transmission;
  • Objenesis, a third-party library.

Object creation steps

Look at the creation process of the object from the bytecode:

Sample code:

public class ObjectTest {
    
    
    public static void main(String[] args) {
    
    
        Object obj = new Object();
    }
}

Bytecode:

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class java/lang/Object
         3: dup           
         4: invokespecial #1                  // Method java/lang/Object."<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 9: 0
        line 10: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
            8       1     1   obj   Ljava/lang/Object;
}

1. Determine whether the class corresponding to the object is loaded, linked, and initialized

  1. When the virtual machine encounters a new instruction, first check whether the parameters of this instruction can locate a symbolic reference of a class in the constant pool of Metaspace (method area), and check whether the class represented by this symbolic reference has been loaded, parsed and initialized . (That is, to determine whether the meta-information exists);
  2. If the class is not loaded, then in the parent delegation mode, use the current class loader to find the corresponding .class file with ClassLoader + package name + class name key. If the file is not found, ClassNotFoundException will be thrown. If it is found, The class is loaded, and the corresponding Class object is generated.

2. Allocate memory for the object

  1. First calculate the size of the space occupied by the object, and then divide a block of memory in the heap for the new object. If the instance member variable is a reference variable, just allocate the reference variable space, which is 4 bytes in size;
  2. If the memory is regular: use pointer collision to allocate memory.
    • If the memory is regular, the virtual machine will use the Bump The Point method to allocate memory for the object. It means that all the used memory is on one side, the free memory is stored on the other side, and a pointer is placed in the middle as an indicator of the dividing point. Allocating memory is just moving the pointer to the free memory for a distance equal to the size of the object. .
    • If the garbage collector chooses Serial, ParNew, which is based on a compression algorithm, the virtual machine uses this allocation method. Generally, when using a collector with a Compact (organization) process, pointer collisions are used.
    • The mark compression (defragmentation) algorithm will defragment the memory. One side of the heap memory stores objects, and the other side is a free area.
  3. If the memory is not regular: free list.
    • If the memory is not regular, the used memory and the unused memory are interleaved with each other, then the virtual machine will use the free list to allocate memory for the object. It means that the virtual machine maintains a list to record which memory blocks are available. When redistributing, find a large enough space from the list to divide the object instance and update the content on the list. This allocation method became the "Free List (Free List)".
    • The choice of allocation method is determined by whether the Java heap is regular or not, and whether the Java heap is regular or not is determined by whether the garbage collector used has a compression function.
    • After the mark-sweeping algorithm cleans up the heap memory, there will be many memory fragments.

3. Deal with concurrency issues

  1. Use CAS + failure retry to ensure the atomicity of the update;
  2. Pre-allocate TLAB for each thread-set by setting -XX:+UseTLAB parameter (area locking mechanism);
  3. Allocate an area for each thread in the Eden area.

4. Initialize the allocated space

  1. All properties are set to default values ​​to ensure that the object instance fields can be used directly without assigning values.
  2. The order of assigning values ​​to object properties:
    • Initialization of the default value of the property
    • Display initialization/code block initialization (parallel relationship, who is first and who will see the order of code writing)
    • Initializer

5. Set the object header of the object

  • Store the object's class (that is, the metadata information of the class), the object's HashCode, the object's GC
    information, lock information and other data in the object's object header. The specific setting of this process depends on the JVM implementation.

6. Execute the init method to initialize

  1. From the perspective of a Java program, initialization has only officially begun. Initialize the member variables, execute the instantiated code block, call the constructor method of the class, and assign the first address of the object in the heap to the reference variable;
  2. So in general (determined by the invokespecial instruction in the bytecode), the init method will be executed after the new instruction to initialize the object according to the programmer's wishes, so that a truly usable object is considered to be created.

Look at the init method from a bytecode perspective

/**
 * 测试对象实例化的过程
 *  ① 加载类元信息 - ② 为对象分配内存 - ③ 处理并发问题  - ④ 属性的默认初始化(零值初始化)
 *  - ⑤ 设置对象头的信息 - ⑥ 属性的显式初始化、代码块中初始化、构造器中初始化
 *
 *
 *  给对象的属性赋值的操作:
 *  ① 属性的默认初始化 - ② 显式初始化 / ③ 代码块中初始化 - ④ 构造器中初始化
 */

public class Customer{
    
    
    int id = 1001;
    String name;
    Account acct;

    {
    
    
        name = "匿名客户";
    }
    public Customer(){
    
    
        acct = new Account();
    }

}
class Account{
    
    

}

Bytecode information:

 0 aload_0
 1 invokespecial #1 <java/lang/Object.<init>>
 4 aload_0
 5 sipush 1001
 8 putfield #2 <com/atguigu/java/Customer.id>
11 aload_0
12 ldc #3 <匿名客户>
14 putfield #4 <com/atguigu/java/Customer.name>
17 aload_0
18 new #5 <com/atguigu/java/Account>
21 dup
22 invokespecial #6 <com/atguigu/java/Account.<init>>
25 putfield #7 <com/atguigu/java/Customer.acct>
28 return

The bytecode instructions of the init() method:

  • The default value of the attribute is initialized: id = 1001;
  • Display initialization/code block initialization: name = "Anonymous Client";
  • Constructor initialization: acct = new Account();

The memory layout of the object
Insert picture description here
Note: what the type pointer points to is actually the meta-information stored in the method area.

Summary of memory layout

Insert picture description here

Object access location

How does the JVM access its internal object instances through the object references in the stack frame?
Insert picture description here
Positioning, accessed by reference on the stack

Two ways of accessing objects: handle access and direct pointer:

1. Handle access

  • Disadvantages: a space is opened up in the heap space as the handle pool, and the handle pool itself will also take up space; the objects in the heap can be accessed through two pointer accesses, which is inefficient.
  • Advantages: The reference stores the stable handle address. When the object is moved (it is common to move the object during garbage collection), only the instance data pointer in the handle can be changed, and the reference itself does not need to be modified.
    Insert picture description here

2. Direct pointer (adopted by HotSpot)

  • Features: The direct pointer is a reference in the local variable table, which directly points to the instance in the heap, and there is a type pointer in the object instance, which points to the object type data in the method area.
  • Disadvantages: The value of the reference needs to be modified when the object is moved (it is common to move objects during garbage collection).
    Insert picture description here

Guess you like

Origin blog.csdn.net/qq_33626996/article/details/114652416