1. Object instantiation
1.1 Object Creation Method
- New (using the constructor)
- The most common way
- Deformation 1: static method of Xxx
- Transformation 2: static method of XxxBuilder/XxxFactory
- A Class of newInstance ()
- Mode of reflection
- Only the constructor of empty parameters can be called, and the permission must be public
- The Constructor of the newInstance ()
- Mode of reflection
- Empty arguments, parameterized constructors can be called, and permissions are not required
- clone()
- Without calling any constructors, the current class needs to implement the Cloneable interface and implement the Clone () method
- Use deserialization
- A binary stream of an object that can be retrieved from a file, network, etc
- Third-party library Objenesis
1.2 Steps for object creation
1.2.1 From the bytecode perspective
The test code
package com.nasuf.jvm;
public class ObjectTest {
public static void main(String[] args) {
Object obj = newObject(); }}Copy the code
Part of the bytecode is as follows:
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
// The class loader is required to load the Object class. At the same time, the corresponding object space is allocated in the heap space, and then zero value initialization
3: dup // Make a copy of the reference in the operand stack, one for the assignment and one for the handle
4: invokespecial #1 // Method Java /lang/Object."
":()V author note: call the empty parameter constructor to explicitly initialize the assignment
7: astore_1 // Add the obj variable from the operand stack to the local variable table at index 1
8: return
LineNumberTable:
line 5: 0
line 6: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
8 1 1 obj Ljava/lang/Object;
Copy the code
1.2.2 From the perspective of execution process
- Determines whether the corresponding class of the object is loaded, linked, or initialized
The virtual machine checks to see if a new instruction’s parameters locate a symbolic reference to a class in Metaspace’s constant pool, and to see if the class represented by the symbolic reference has been loaded, parsed, and initialized (that is, if the class meta information exists). If not, use the current ClassLoader in parental delegate mode to find the corresponding. Class file with ClassLoader + package name + class name key. If no file is found, a ClassNotFoundException is thrown; If found, the Class is loaded and the corresponding Class object is generated
- Allocates memory for objects
The size of the object is calculated, and a chunk of memory is allocated to the new object in the heap. If the instance object variable is a reference variable, only the reference variable space is allocated, which is 4 bytes
- If The memory is neat, The virtual machine will Bump The Pointer to allocate memory for The object. This means that all the used memory is on one side and all the free memory is on the other, with a pointer in the middle as a pointer to the dividing point. Allocating memory simply moves the pointer to the free memory by a distance equal to the size of the object. If the garbage collector chooses Serial, ParNew, etc. based on compression algorithms, the virtual machine uses this allocation method. That is, pointer collisions are typically used with collectors with a compact process.
- If memory is not tidy and used memory and unused memory are interlaced, the virtual machine will use the Free List method to allocate memory for objects. The virtual machine maintains a list of memory blocks that are available, finds a large enough space from the list to allocate to object instances, and updates the list. This type of allocation is called a free list.
The choice of allocation method depends on whether the Java heap is clean, which in turn depends on whether the garbage collector used has collation capabilities
- Handle concurrency security issues
- Compare And Swap (CAS) failed Retry And region locking ensure atomicity of pointer update operations
- TLAB allocates a small chunk of memory in the Java heap for each Thread, which is called the Thread Local Allocation Buffer (TLAB). Specifies whether the VM uses TLAB
-XX:+/-UseTLAB
Parameter to set
- Initialize the allocated space
All properties are set to default values, ensuring that object instance fields can be used directly without assigning values
- Sets the object header of the object
The object’s owning class (that is, the metadata information of the class), the object’s HashCode, and the object’s GC information, lock information and other data are stored in the object’s object header. How this process is set up depends on the JVM implementation.
- Execute the
method to initialize
From a Java program’s point of view, initialization begins. Initialize the member variable, execute the instantiation code block, call the constructor of the class, and assign the first address of the heap object to the reference variable. Therefore, in general (depending on whether the bytecode is followed by the Invokespecial instruction), the new instruction will be followed by the execution method to initialize the object as the programmer wishes, so that a truly usable object is fully created
2. Memory layout of the object
2.1 Object Headers
Runtime metadata (Mark Word)
- Hash values (HashCode)
- GC generational age
- Lock status flag
- The lock held by the thread
- Biased thread ID
- Bias timestamp
Type a pointer
Point to the metadata InstanceKlass to determine the type to which the object belongs
If it is an array, record the length of the array
2.2 Instance Data
It is the valid information that the object actually stores, including the various types of fields defined in the program code (both inherited from parent classes and owned by itself). The rule is:
- Fields of the same width are always assigned together
- Variables defined in a parent class appear before subclasses
- If the CompactFields argument is true (the default is true) : the narrow variable of the subclass may be inserted into the gap of the parent class variable
2.3 Align Padding
It’s not necessary, it’s not meaningful, it’s just a placeholder
For the following code
package com.nasuf.jvm;
public class Customer {
int id = 1001;
String name;
Account acct;
{
name = "anonymous client";
}
public Customer(a) {
acct = newAccount(); }}class Account {}
Copy the code
package com.nasuf.jvm;
public class CustomerTest {
public static void main(String[] args) {
Customer cust = newCustomer(); }}Copy the code
The memory structure is as follows:
3. Access and locate objects
How does the JVM access an internal object instance through an object reference in a stack frame?
There are two main ways to access objects:
3.1 Handle Access
- Benefits: Reference stores the stable handle address, and only changes the instance data pointer in the handle when the object is moved (which is common in junk phone). Reference itself does not need to be modified
- Disadvantages: Need an extra space to store the handle, object lookup is not direct
3.2 Direct Pointers (adopted by Hotspot)
- Benefits: Object address access is relatively straightforward
- Disadvantages: Reference data needs to be modified when the object is moved