JVM-HotSpot Virtual Machine Object Exploration

Table of contents

1. Instantiation of objects

(1) How to create objects

(2) Steps to create objects

2. Memory layout of objects

(1) Object header

(2) Example data

(3) Alignment filling

3. Object access positioning

(1) Using handles

(2) Direct pointer

(3) Comparison


1. Instantiation of objects

(1) How to create objects

  1. new
  2. Class newInstance
  3. Constructor的newInstance
  4. Use clone
  5. Use deserialization
  6. Third-party library Objenesis

(2) Steps to create objects

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

When the virtual machine encounters a bytecode new instruction. First check whether the parameter of this instruction can locate a symbol reference of a class in the constant pool, and check whether the class represented by this symbol reference has been loaded, parsed and initialized. If not, in the parent delegation mode, use the current class loader to find the corresponding .class file using the ClassLoader + package name + class name key value. If the file is not found, a ClassNotFoundException exception will be thrown.

2. Allocate memory for the object

First calculate the size of the space occupied by the object, and then allocate a piece of memory in the heap to the new object. If the instance member variable is a reference variable, only allocate the reference variable space, that is, 4 bytes in size

If there are irregularities in the Java heap memory, the virtual machine must maintain a list of which memory is available and which is not. When allocating, find a large enough space in the list to allocate, and then update the list. This allocation method is called Free List.

Which one to choose depends on whether the Java heap is regular or not. Whether the Java heap is regular or not depends on whether the garbage collector used has the ability to compress space (Compact).

  • When using collectors with compression and sorting processes such as Serial and ParNew, pointer collision is simple and efficient;
  • When using the CMS collector based on the Sweep algorithm, only the free list can be used to allocate memory; (CMS has designed a Linear Allocatioin Buffer allocation buffer in order to allocate memory faster in most cases, and obtain the memory through the free list. After allocating a large buffer, you can still use pointer collision to allocate it)

Assume 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 a demarcation point indicator. Then the memory allocation is an example of the pointer pointing in the free direction and moving a section equal to the size of the object. This allocation method is called Bump The Pointer.

3. Handle concurrency security issues

Object creation is a very frequent behavior, and it is also necessary to consider that in concurrency situations, it is not safe to just modify the location pointed by a pointer. For example, memory is being allocated to object A, the pointer has not been modified, and object B uses the original pointer to allocate memory. . There are two options to solve the problem:

  • a. Synchronize the action of allocating memory space. In fact, the virtual machine adopts CAS with failure retry to ensure the atomicity of the update operation.
  • b. Divide the memory allocation action into different spaces according to threads. Each thread pre-allocates a small piece of memory in the Java heap, which is called a local thread Allocation buffer (Thread Local Allocation Buffer, TLAB), synchronization lock is required only when the local buffer is used up and a new buffer is allocated.

Whether the virtual machine uses TLAB can be set through the -XX: +/-UseTLAB parameter.

4. Initialize the allocated space

After the memory allocation is completed, the virtual machine will initialize the allocated memory space (excluding the object header) to zero values. If TLAB is used, this work can be performed in advance when TLAB is allocated.

This step ensures that the instance field of the object can be used directly in the Java code without assigning an initial value, and the program can access the zero value corresponding to the data type of the field.

5. Set the object header of the object

Next, the Java virtual machine also needs to make necessary settings for the object, such as which class instance the object is, how to find the metadata information of the class, and the hash code of the object (actually the HashCode of the object will delay the actual call to Object:: It is calculated only with the hashCode() method), the GC generation age of the object and other information. This information is stored in the object header (Object Header) of the object.

6. Execute the init method for initialization

After the above work is completed, from the perspective of the virtual machine, a new object has been generated, but from the perspective of the Java program, the object creation has just begun, and the object's construction method (init() method in the Class file) has not yet been created. When executed, all fields have default zero values. After the new instruction, the init method is executed to initialize the object according to the programmer's wishes, so that a truly usable object is completely constructed.

2. Memory layout of objects

(1) Object header

The object header consists of two parts. The first type is to store the runtime data of the object itselfMark Word, and the second type isType pointer

The length of this part of data is 32bit and 64bit respectively for 32-bit and 64-bit virtual machines (pointer compression is not enabled), and is officially called[Mark Word]Runtime metadata, which includes:

  • hash value
  • GC generation age
  • lock status flag
  • The lock held by the thread
  • Prefer thread ID
  • bias timestamp

The information in the object header is additional storage cost that has nothing to do with the data defined by the object itself. Taking into account the space efficiency of the virtual machine, Markword can reuse its own space depending on the object status.

type pointer

That is, the object points to its type metadata pointer. The Java virtual machine uses this pointer to confirm which class instance the object belongs to.

Note:If the object is a Java array, there must be a piece of data in the object header to record the length of the array, because The virtual machine can determine the size of the Java object through the metadata information of ordinary Java objects, but if the length of the array is uncertain, it will not be able to pass the metadata The size of the array is inferred from the information in .

(2) Example data

The instance data part of the object is the actual stored effective information of the object, that is, the various types of data we define in the program code. Field contents, whether inherited from the parent class or fields defined in the subclass, must be recorded.

1. The storage order of this part will be affected by the order in which the virtual machine allocation policy parameters and fields are defined in the Java source code.
2. Allocation strategy parameters -XX:FieldsAllocationStyle
3. The default allocation order of the HotSpot virtual machine is longs/doubles, ints, shorts/chars, bytes/booleans , oops (Ordinary Object Pointers)
4. It can be seen from the default allocation strategy that fields of the same width are always allocated and stored together.
5. When this prerequisite is met, variables defined in the parent class will appear before the subclass.
6. If the +XX: CompactFields parameter value of the HotSpot virtual machine is true (the default is also true), then narrower variables in the subclass are also allowed to be inserted into the gaps of the parent class variables to Save a little space.

(3) Alignment filling

Alignment padding does not necessarily exist and has no special meaning. It only serves as a placeholder.

Because the HotSpot virtual machine automatic memory management system requires that the starting address of the object must be an integer multiple of 8 bytes. In other words, the size of any object must be an integer multiple of 8 bytes.

The object header has been carefully designed to be an integer multiple of 8 bytes, 1 times or 2 times. If the object instance data part is not aligned, it needs to be filled in to complete it.

3. Object access positioning

(1) Using handles

Using handles, a piece of memory will be allocated in the Java heap as a handle pool. What is stored in the reference is the handle address of the object. The handle contains specific information about the object instance data and type data.

(2) Direct pointer

Using pointers, what is stored in the reference is directly the object address. If you access the object itself, there is no need for the overhead of one more indirect access.

(3) Comparison

Both methods have their own advantages:

  • The biggest advantage of using a handle is that the reference stores a stable handle address. When the object is moved (generated during garbage collection), only the instance data pointer in the handle changes, and the reference itself does not need to change.
  • The biggest advantage of using pointers is that it is fast and saves the time overhead of pointer positioning. Since object access is very frequent in Java, adding up a little adds up to a considerable execution cost.
  • HotSpot mainly uses pointers for object access (exception, if the Shenandoah collector is used, there will be an additional forwarding).

Guess you like

Origin blog.csdn.net/m0_62946761/article/details/133974995