As you know, Java is an object-oriented programming language. We usually use a variety of objects while writing code. So when you write
User user = new User();
such a line of code, what does the JVM do?
II. Understand the object
- Memory Layout
The memory layout of an object in the Hotspot virtual machine is divided into three parts: Object Header, Instance Data, and Alignment Padding.
- The object header has two parts of information. The first part is used to store the running data of the object itself (HashCode, GC generation age, lock status flag, etc.). The other part is the type pointer, which points to its class metadata. The virtual machine uses this pointer to determine which instance of the class this object is (if there is a handle pool method there is no such thing). If it is an array, there will also be a record array length as shown in the following table:
|Mark Word||Object hashCode or lock information, etc.|
|Class Metadata Address||Object type data pointer|
|Array length||the length of the Array|
Mark Word is a non-fixed data structure that stores as much information as possible in a very small space, and it multiplexes its own storage space based on the state of the object. The contents of the storage in each state are as follows:
|Flag bit||status||storage content|
|01||Unlocked||Object HashCode, age of generation|
|00||Lightweight lock||Pointer to lock record|
|10||heavyweight lock||Pointer to lock record|
|01||biased||biased thread ID, biased timestamp, object age|
The instance data portion is the valid information that is actually stored, that is, the various types of field content defined in the code. Whether it is inherited by the parent class or in the child class.
Align padding does not have to exist, it only acts as a placeholder because the HotSpot virtual machine requires that the object's starting address must be an integer multiple of 8 bytes.
2.The object's access
In Java programs we manipulate an object by pointing to a reference to this object. We all know that the object exists in the heap, and this reference exists in the virtual machine stack. So how does the reference locate the location of the objects in the heap?
- Direct pointer method (HotSpot implementation): The address stored directly in the reference is the address of the object in the heap. The advantage is that the positioning speed is fast, and the disadvantage is that the object movement (the object movement when the GC moves) itself needs to be modified.
- Handle method: Part of the Java heap is used as a handle pool. The reference stores the handle address of the object, and the handle includes the specific location information of the object instance and type. The advantage is that object movement only changes the instance data pointer in the handle, the disadvantage is two positioning.
- The procession of creating an object
When the virtual machine encounters a new instruction, it checks whether the parameters of this instruction can locate a symbolic reference to a class in the constant pool and checks whether the represented class has been loaded by the class loader. If it is not loaded then the loading of this class must be performed first.
After the class load check is passed, the virtual machine will allocate memory for the new object, and the size of the memory required by the object can be determined after the class is loaded.
After the memory allocation is completed, the virtual machine needs to initialize the object to a value of zero, so that the instance variable of the object can be directly used without the initial value in the code. The class variable is initialized to a value of zero during the preparation phase of the class loading.
Set the necessary information for the object header, such as how to find the metadata information of the class, the hashCode of the object, the age of the GC, and so on.
After the above operation, a new object has been generated, but the
method has not been executed, and all fields are zero. At this time, you need to execute the method (construction method) to initialize the object according to the programmer's wishes. The initialization operation of the class variable is completed in the initialization phase of the class loading method.
There are two ways to allocate memory:
The Java heap memory is regular (using a markup or a garbage collector with compression), using a pointer to the free location, and allocating memory moves the pointer equal to the allocated size.
- The memory is not regular (the garbage collector using the markup cleanup), the virtual machine maintains a list of available memory blocks, and when the memory is allocated, a large enough memory space is found from the list to allocate the object and update the available memory list.
A GC is triggered when sufficient memory cannot be found
Concurrency problem solution when allocating memory:
Synchronize the actions of allocating memory space---use “the CAS failure retry” to ensure the atomicity of the update operation.
Each thread pre-allocates a small amount of memory in the heap, called the Thread Local Allocation Buffer (TLAB), which thread allocates memory on its TLAB, only when the TLAB runs out and allocates a new TLAB. Synchronization lock is required. Set by the -XX:+/-UseTLAB parameter.
- Create object instruction reordering problem
A a = new A();
A simple decomposition of an object:
- Allocate the memory space of the object
- Initialization object
- Set the reference to the allocated memory address
In the case of 2, 3 and 2 steps, the instruction reordering occurs, which causes problems when accessing the object before initialization in the case of multithreading. The “Double Detection Lock” mode of the singleton mode has this problem. You can use “volatile” to disable instruction reordering to solve problems.