Directly above:

1. Class loading check

When a new instruction is encountered, the first step is to check the static constant pool to see if the symbol reference corresponding to the instruction can be found. Then the second step is to check whether the symbol reference corresponding to the class has been loaded — connected — initialized. If so, the second step is to load the class first.

2. Allocate memory

When the class load check is passed, the size of the object is determined after the class load is completed, so the newly created object is allocated memory based on the size of the object. This memory is divided in the heap. In general, there are two ways to allocate memory: “pointer collision” and “free list”. The choice of allocation method depends on whether the Java heap is clean, and whether the Java heap is clean depends on whether the garbage collector is compressed or not.

Pointer to the collision

If the Memory of the Java heap is absolutely neat, all used memory is placed on one side, free memory is placed on the other, and a pointer is placed in the middle as an indicator of the dividing point, then the allocated memory simply moves that pointer to the free space by a distance equal to the size of the object. Conclusion:

  • Heap state: tidy
  • Corresponding garbage collectors: Serial, ParNew
  • Corresponding garbage collection algorithm: replication algorithm

The free list

If the memory in the Java heap is not tidy, the memory used and the memory in space are interlocked, and the virtual machine must maintain a free list of which memory blocks are available and find a large enough space in the list for objects to use at allocation time. Conclusion:

  • Heap state: not tidy
  • Corresponding garbage collector: CMS
  • Corresponding garbage collection algorithm: tag sweep

Concurrency issues

Partition is not necessarily thread-safe in the case of concurrency. It is possible to allocate memory to object A, but the pointer has not been changed, and object B also uses the original pointer to allocate memory.

  • CAS+ retry on failure: Use the CAS optimistic lock to try to update the operation. If the CAS fails, retry until the operation succeeds.
  • TLAB: allocate a pre-stored address space named TLAB in Eden area of heap memory for each thread in advance. This memory can be used when creating objects. When TLAB space is used up, the CAS+ failed retry method is used to allocate memory.

3. Initialize the zero value

As we learned from the class loading process, final static variables are directly assigned initial values during preparation, and static variables are assigned zero values. But for ordinary member variables we do not know when the initialization, so this stage is to initialize the member variable. The virtual machine needs to initialize all the data types in the allocated memory space to zero (excluding the object header). This step ensures that the instance fields of the object can be used in Java code without assigning initial values, and the program can access the zero values corresponding to the data types of these fields.

4. Set the object header

After initializing the zero value, the virtual machine sets up the object as necessary, such as which class the object is an instance of, how to find the metadata information about the class, the object’s hash code, the object’s GC generation age, and so on. This information is stored in the object header. In addition, the object header can be set differently depending on the running status of the VM, for example, whether biased locking is enabled.

Point to the init method

After all the work is done, from the virtual machine’s point of view, a new object has been created, but from the Java program’s point of view, object creation has just begun, methods have not been executed, and all fields are still zero. So, in general, a new instruction is followed by a method that initializes the object as the programmer wants it to be, and then a usable object is fully generated.

Take a look at the memory layout of the object

The object header of the Hotspot virtual machine contains two parts of information. The first part is used to store the object’s own runtime data (hash code, GC generation age, lock status flag, etc.) and the second part is a type pointer, a pointer to the object’s class metadata. The virtual machine uses this pointer to determine which class the object is an instance of. 2. Instance data This place is the real valid information stored in the object, as well as the various types of field content defined in the program. 3. Align padding The padding part is not necessary and has no special meaning. It only serves as a placeholder. Because the Hotspot VIRTUAL machine’s automatic memory management system requires that the object’s starting address be an integer multiple of 8 bytes, in other words, the object’s size must be an integer multiple of 8 bytes. The object header is exactly a multiple (1 or 2) of 8 bytes, so when the object instance data part is not aligned, it needs to be filled by alignment.

Object access mode

Handle:



If you are usinghandleIf so, the Java heap will be allocated a chunk of memoryHandle to the pool.referenceIs stored in the objectHandle to the addressAnd the handle containsObject instance datawithType dataTheir specific address information.

Direct Pointers



If you are usingDirect PointersThen the layout of Java heap objects must consider how to place information about accessing type data, andreferenceStore the address of the object directly in.

There are advantages to both methods of accessing objects. The biggest benefit of using handles for access is that reference stores a stable handle address and only changes the instance data pointer in the handle when the object is moved. Reference itself does not need to be modified. The biggest advantage of using direct pointer access is fast speed, it saves the time cost of a pointer location.

  • Object instance data: this is the object information (object header, instance data and alignment padding) that comes out of new.
  • Object type data: Class information (object type, parent Class, implemented interface, method, etc.) about the corresponding Class of the object instance, including method area. Object type data in the access method area is accessed through Pointers to object type data.

Supplement:

When invoking an instance method by instance reference, first find the object type data in the corresponding method area through the object instance data, and then find it in the parent class type information if it cannot find it.

If the inheritance level is deep and the method to be called is in the parent class higher up, the call is inefficient because each call requires many lookups. In this case, most systems use a method called virtual method table to optimize the efficiency of calls.

The so-called virtual method table is to create a table for each class when the class is loaded. This table includes all dynamically bound methods of the object of the class and their addresses, including the methods of the parent class. However, a method has only one record, and only the subclass will retain the subclass after overwriting the parent class method. When you dynamically bind methods through objects, you only need to look up the table instead of looking up each parent class.