2.2 Runtime data area

2.2.1 Program Counter Register

The PC register in the JVM is an abstract simulation of the physical PC register: it stores the address that points to the next instruction and the instruction code that is about to be executed. The execution engine reads the next instruction

The program counter is a small memory space (storing only instruction addresses) and is the only area where the JVM specification does not specify any OutOfMemoryError cases.

Can be seen as an indicator of the line number executed by the current thread. Used to instruct the thread to select the next bytecode to execute. Counters do not affect each other between threads, are stored independently, “thread private” memory, and the life cycle is consistent with the life cycle of the thread.

  • The thread is executing a Java method, and the counter records the address of the virtual machine bytecode instruction being executed
  • When the Native method is executed, the counter value is Undefined

Example: For the following code

public class Test {

    public static void main(String[] args) {
        int i = 10;
        int j = 20;
        int k = i + j;

        String s = "abc"; System.out.println(i); System.out.println(k); }}Copy the code

usejavap -v Test.classAfter decompiling, you get the following

Two common questions:

  1. What is the use of using PC registers to store byte code instruction addresses? Why use a PC register to record the execution address of the current thread?

    The CPU has to keep switching threads, and when it switches back, it needs to know where to start

    The JVM’s bytecode interpreter needs to change the value of the PC register to figure out what bytecode instruction to execute next

  2. Why are PC registers set to be thread private

    In order to accurately record the current address of the bytecode instructions being executed by each thread, it is best to assign one to each thread

2.2.2 Java Vm Stack

The stack is a run-time unit and the heap is a storage-time unit

The stack solves the running problem of the program, how does the program run, or how does it handle data

The heap solves the problem of data storage: where and where does the data go

The thread is private and has the same life cycle as the thread

2. Two kinds of exceptions occur in this region

  1. StackoverflowError: The stack depth of the thread request is greater than the virtual machine allows

    -xss256K: count-2214 */
    public class Test {
        private static int count = 1;
        public static void main(String[] args) { System.out.println(count++); main(args); }}Copy the code
  2. OutOfMemoryError: Most vm stacks can be dynamically expanded. If sufficient memory cannot be allocated during the expansion process

3. Storage unit of stack

The data in the Stack is in a Stack Frame format, one for each method. A stack frame is a block of memory, a data set that holds various data information during the execution of a method

4. Operation principle of stack

Stack operation: push the stack, out of the stack

In a thread, only one stack frame is active at a time:

Only stack frames of the currently executing method are valid, called Current Frame.

The Method corresponding to the Current stack frame is called the Current Method.

The Class that defines this method is called Current Class.

All bytecode instructions run by the execution engine operate only on the current stack frame

If the method calls another method, a new stack frame is created and placed at the top of the stack, called the new current frame

You cannot reference a stack frame in another thread in one stack frame

Both the return command and the exception thrown cause the stack frame to be ejected

5. Internal structure of stack frame

Local Variables

Operand Stack (or expression Stack)

Dynamic Link (or method reference to runtime constant pool)

Method Return Address (or definition of method normal or abnormal exit)

Some additional information

6. Local variation scale

Also known as local variable arrays or local variable tables, Javap decompiles LocalVariableTable in bytecode files

Is defined as a numeric array for storing method parameters and local variables defined in the method body

These data types include: basic data type, object reference, and returnAddress type

Local variable table is built on the stack of threads, there is no data security problem

The required capacity of the local variable table is determined at compile time

The table size does not change while the method is running

7. Understanding slot

The most basic unit of storage for a local variable table is Slot

In a local variable table, only one slot (including the returnAddress type) is available for types up to 32 bits

Byte, short, and char are converted to int before storage

Boolean also converts to int: 0-false, non-0-true

64-bit types (long and double) occupy both slots

When an instance method is called, its method parameters and local variables defined inside the method body are copied to each slot in the local variable table in sequence

If you need to access the value of a 64bit local variable in the local variable table, you only need to use the previous index

If the current frame is created by a constructor or instance method, the this pointer is stored in slot of index0

8. Slot reuse

If a local variable goes out of its scope, new local variables declared after its scope may reuse the expired local variable slot, saving resources

9. Static versus local variables

Class variables are initialized twice:

  1. Preparation phase: Set zero values for class variables
  2. Initialization phase: Assigns initial values defined in the code

There is no initialization for the local variable table, meaning that local variables must be manually initialized

public void test4(a) {
    int i;
    System.out.println(i); // Variable 'i' might not have been initialized
}
Copy the code

Operand stack

During the execution of a method, data is written to or extracted from the stack according to bytecode instructions, that is, on and off the stack

Operand stack, mainly used to store the intermediate results of the calculation process, and as a temporary storage space for variables during the calculation process

The operand stack is a workspace of the JVM’s execution engine. When a method starts executing, a new stack frame is created and the operand stack of the method is empty

The operand stack determines the stack depth at compile time to store values, stored in the code-stack property

    Code:
      stack=2, locals=2, args_size=1
         0: sipush        1111
         3: istore_1
         4: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
         7: iload_1
         8: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
        11: return

Copy the code

Any element in the stack can be any Java data type

The 32bit type occupies one stack unit depth

64-bit types occupy two stack units of depth

If the called method has a return value, the return value is pushed into the operand stack of the current frame and updates the NEXT bytecode instruction to be executed in the PC register

The JVM’s interpretation engine is a stack-based execution engine, where the stack is the operand stack

11. Top-of-stack Caching

Operands are stored in memory. Frequent memory read/write operations affect the execution speed. Therefore, all the elements at the top of the stack are cached in the registers of the physical CPU to reduce the number of memory read/write operations and improve the execution efficiency of the execution engine

12. Dynamic linking

The stack frame contains a reference to the method that the stack frame belongs to in the runtime constant pool. The goal is for the code supporting the current method to be dynamically linked

In a bytecode file, all variable and method references are kept as Symbolic references in the class file’s constant pool, and dynamic linking is used to translate these Symbolic references into direct references to the calling method

Constant pool provides symbols and constants for instruction identification

13. Method invocation

In the JVM, the conversion of symbolic references to direct references to calling methods is related to the method binding mechanism

When bytecode is reproduced into the JVM, the process of converting symbolic references to direct references is called static linking when the target method being called is known to the compiler and remains unchanged during runtime

Conversely, if the method being called cannot be determined at compile time but only at program runtime, it is called dynamic linking

Binding mechanism — Polymorphism:

Binding is the process by which a symbolic reference to a field, method, or class is replaced with a direct reference

Early binding: Symbolic references are converted to direct references using static links when the invoked method is known at compile time and remains unchanged at run time

Late binding: Binding can only be done during program execution based on dynamic links

Method invocation: virtual method and non-virtual method

Non-virtual methods: The version of the call is determined at compile time and is immutable at run time. Static methods, private methods, final methods, instance builders, superclass methods

Other methods are called virtual methods

Ordinary call instructions:

  1. Invokestatic: Invokes static methods, and the parsing phase determines the unique version of the method
  2. Invokespecial: Call the

    method, private and parent methods, and determine the unique method version in the parsing phase
  3. Invokevirtual: invokes all virtual methods (final also uses this instruction, but is non-virtual; Custom methods are also used for this directive.
  4. Invokeinterface: Invokes interface methods

Dynamic call instruction:

  1. Invokedynamic: Dynamically resolves the method to be invoked and executes it

    Enable the JVM to support dynamically typed languages

    Is used in the lamda expression

Statically typed languages: Check for types at compile time – Java

Dynamically typed languages: Check for types at runtime — JS, Python

15. Method invocation: The essence of method rewriting

  1. Find the instance type of the object executed by the first element at the top of the operand stack, call it C;
  2. If C finds a method that matches both the descriptor and the simple name in the constant, the permission access check is performed. If it passes, the direct reference of the method is returned, and the search process ends. If it does not pass, IllegalAccessError is returned
  3. Otherwise, search and verification process in 2 will be carried out for each parent class of C from bottom to top according to inheritance relationship;
  4. AbstractMethodError is raised if an appropriate method is never found

To improve performance and reduce the search process, the JVM creates virtual method tables for very frequent dynamic allocation processes. Instead of looking up a virtual method table for each class, the JVM uses an index table. The virtual method table, which holds the actual entry points for each method, is created and initialized during the linking phase of the class load. After the class’s variable initialization values are ready, the JVM also initializes the method table for that class

16, method return address

Holds the value of the PC register that called the method

Method A calls method B at line 3

When method B finishes, let the execution engine continue with line 4 of method A

Return instruction at normal end:

ireturn : boolean, byte, char, short, int

lreturn : long

freturn : float

dreturn : double

Areturn: indicates the reference type

Return: void method, instance initialization method init, class and interface initialization method Clinit


Return instruction at the end of exception:

Stored in the exception handling table, easy to find the exception handling code

Exit by exception does not return any value to the upper caller

2.2.3 Local method stack

The Native method used by the virtual machine is otherwise the same as the virtual machine stack. Throws StackoverflowError (such as recursively calling N times) and OutOfMemoryError (not enough memory to expand or create a new thread)

2.2.4 Java heap

An area of memory shared by all threads that is created when the virtual machine is started. The sole purpose of this area is to hold object instances.

The Java heap is the primary area managed by the garbage collector.

The Java Virtual Machine specification states:

  1. The Java heap can be in a physically discrete memory space, as long as it is logically contiguous
  2. When implemented, it can be either fixed or extensible
  3. OutOfMemoryError is thrown if there is no memory in the heap to complete the power allocation and the heap cannot be extended

2, the core of the heap overview: memory segmentation

Agreement: New area = new generation = young generation, pension area = old age area = old age, permanent area = permanent generation

Java7 and previous heap memory is logically divided into new, old, and permanent

Young Generation Space Young/New

| – was divided into Eden and Survivor

Tenure Generation Space Old/Tenure

Permanent Space Perm of the Permanent area

Java8 and subsequent heap memory is logically divided into: new area, pension area, meta space

Young Generation Space Young/New

| – was divided into Eden and Survivor

Tenure Generation Space Old/Tenure

Meta Space Meta Space

For the following code

/** * -Xms10m -Xmx10m */
public class Test {
    public static void main(String[] args) {
        System.out.println("start...");
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end..."); }}Copy the code

After running, you can see the allocation between the new generation and the old generation through Java visualVM

3. Set heap space size

-xms (memory start) indicates the initial memory of the heap (new generation + old age), equivalent to: -xx :InitialHeapSize

-xmx is used to indicate the maximum memory of the heap area (new generation + old age), equivalent to: -xx :MaxHeapSize

-xms and -xmx are typically configured with the same value to improve performance without the need to repartition the size of the heap after cleaning it up after GC

The default:

InitialHeapSie: Computer physical memory size / 64

MaxHeapSize: computer physical memory size / 4

When printing heap memory through Java, only one survivor region is evaluated, so the printed value is less than the set value

To check heap memory size:

  1. jps + jstatus gc pid
  2. -XX:+PrintGCDetails

The young generation and the old generation

-xx :NewRatio=4, indicating that the ratio of the Cenozoic era is 1, the ratio of the old age is 4 (default is 2).

-xx :SurvivorRatio: sets the ratio of Eden to Survivor zones in the new generation (default: 8)

| – but when using a default value, because the JVM adaptive, may not actual size 8

Almost all objects are created in Eden

5. Object allocation process

  1. The object of new is Eden first, which has a size limit
  2. When Eden is full, YoungGC (MinorGC) is performed to move the still used objects to S0 (age+1).
  3. When Eden is full again, Eden and S0 will be YoungGC to move the still used objects to S1
  4. Repeat steps 2 and 3 until you reach 15 times (default, set by -xx :MaxTenuringThreshod=

    ) to move the object to the old age

The new generation is frequently recycled, the old age is rarely recycled, and the permanent generation/meta-space is almost not recycled

6. MinorGC, MajorGC, FullGC

GC is not always for the new generation, old age, method area together with the recovery, most of the time is the new generation

In Hotspot, GC is divided into:

  1. Partial GC: Instead of collecting the entire Java heap
    1. Minor GC/Young GC: This is just garbage collection for the new generation
    2. Major GC (Old GC) : Just Old GC
      1. Currently, only the CMS GC has a separate collection behavior for older generations
      2. A lot of times the Major GC will be mixed with the Full GC and you need to be specific about whether it is old age or whole heap
    3. Mixed GC: Collect garbage from the whole generation and part of the old age
      1. Currently only the G1 GC has this behavior
  2. Full GC: Collects garbage from the entire Java heap and method area

MinorGC trigger mechanism:

  1. When Eden is full, the Minor GC is triggered. The Minor GC is not triggered when Survivor is full
  2. Java objects tend to be ephemeral, so Minor GC is frequent and fast
  3. The Minor GC causes Stop the World to suspend the user thread until the garbage collection is complete

Old GC (Major GC/Full GC) triggers:

  1. Major GC occurs, often accompanied by at least one Minor GC
    1. That is, if the old decade runs out of space, the Minor GC will be triggered first, and if it continues to run out of space, the Major GC will be triggered
  2. Major GC is generally 10 times slower than Minor GC
  3. If the memory is still insufficient after Major GC, report OOM

Full GC trigger mechanism:

  1. When system.gc () is called, Full GC is recommended, but not otherwise
  2. Old age to lack of space
  3. Method to go out of space
  4. The average size of the old generation after passing the Minor GC is large relative to the available memory of the old generation
  5. If the size of the object is greater than the available memory of S1 when Eden and S0 replicate to S1, the object is migrated to the old age and the available memory of the old age is smaller than the size of the object

7. Memory allocation strategy

  1. Priority allocation Eden
  2. Large objects are allocated directly to the old age
    1. Try to avoid too many large objects in your program
  3. Long-lived objects are assigned to the old age
  4. Age determination of dynamic object n
    1. If the sum of the size of all objects of the same age in region S is greater than half of the region S space, objects older than or equal to that age can go straight to the old age without waiting for the age required in MaxTenuringThreshod
  5. Space allocation guarantee
    1. -XX:HandlerPromotionFailure

8. TLAB (Thread Local Allocation Buffer)

Why TLAB:

The heap is a thread-shared area, and since object instances are created very frequently in the JVM, it is not thread-safe to partition memory from the heap in a concurrent environment,

In order to avoid multiple threads operating on the same address, mechanisms such as locking are needed, thus affecting allocation speed

What is TLAB:

From a memory model perspective, the Eden region continues to be partitioned, and the JVM allocates a private cache region for each thread

When multiple threads allocate memory simultaneously, TLAB can avoid a series of non-thread-safe problems and improve the memory allocation throughput, so we can call this memory allocation method a fast allocation strategy

The JVM uses TLAB as the first choice for memory allocation, but not all instances can be allocated memory in TLAB

You can run -xx :useTLAB to set whether to enable TLAB

By default, TLAB accounts for only 1% of Eden (through – XX: TLABWasteTargetPercent Settings)

When an object fails to allocate memory in TLAB, the JVM tries to use a locking mechanism to ensure atomicity and allocate memory in Eden

Heap space is a common JVM parameter

– xx: HandlerPromotionFailure: after the JDK7 and the value of this parameter will not affect the spatial distribution of the JVM security strategy. As long as the contiguous space of the old generation is larger than the total size of the new generation object or the average size of the previous promotions, Minor GC is performed, otherwise Full GC is performed

10. Escape analysis

If, after Escape Analysis, an object is found to have no Escape method, it may be optimized to allocate memory on the stack so that it does not need to allocate memory on the heap and therefore does not need to GC

When an object is defined in a method and is used only inside the method, no escape is considered to have occurred

// Escape occurs
public StringBuffer test(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb;
}

// No escape will occur
public String test(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb.toString();
}
Copy the code

-xx :+DoEscapeAnalysis: Displays to enable escape analysis

-xx :+PrintEscapeAnalysis: Displays the filtering results of escape analysis

Escape analysis: Code optimization

On the stack


Synchronous elision: If an object is found to be accessible only from one thread, then operations on the object can be considered asynchronous

The JIT uses escape analysis to determine whether a lock object used by a synchronized block can be accessed by only one thread and not published to other threads

If not, the JIT unsynchronizes this part of the code at compile time

// This code itself does not implement secure synchronization
public void test(a) {
    Object lock = new Object();
    synchronized (lock) {
        System.out.println("test"); }}/ / optimization
public void test(a) {
    Object lock = new Object();
    System.out.println("test");
}
Copy the code

Detached objects or scalar replacements: Some objects may be accessible without needing to exist as a contiguous memory structure, so part (or all) of the object can be stored not in memory, but in CPU registers

Scalar: A piece of data that can no longer be decomposed into smaller pieces. Primitive data types in Java are scalars

As opposed to scalars, data that can also be decomposed is called an aggregate quantity, and objects in Java are aggregate quantities because they can be decomposed into other aggregates and scalars

In the JIT stage, if an object cannot be accessed by the outside world after escape analysis, the object will be disintegrated into several contained member variables to replace it, which is called scalar replacement

class Point{
    int x;
    int y;
}

public void test(a) {
    Point point = new Point();
    System.out.println(point.x + "--" + point.y);
}

/ / after optimization
public void test(a) {
    int x = 0;
    int y = 0;
    System.out.println(x + "--" + y);
}
Copy the code

2.2.5 method area

Thread shared areas are used to store data such as class information that has been loaded by the JVM, constants, static variables, code compiled in time by the compiler, and so on.

Garbage collection is relatively rare in this region, where memory collection is targeted at constant pool collection and type offloading. In general, this area does not perform well for collection, especially for type offloads

OutOfMemoryError is thrown when the method area cannot meet memory allocation requirements

1. Interaction between stack, heap and method area

2. Basic understanding of method area

  1. Thread shared area
  2. Created at JVM startup, and its actual physical memory space can be as discontinuous as the heap
  3. Method area size, optionally fixed or extensible
  4. The size of the method area determines how many classes the system can hold. If the system defines too many classes, the method area will overflow OOM
  5. Shutting down the JVM frees up memory in the method area

3. Set the size of method area memory

  1. -xx :MetaspaceSize: The default value depends on the platform. In Windows, the value is 21M
  2. -xx :MaxMetaspaceSize: The default value depends on the platform. On Windows, the default value is -1.

4. Internal structure of method area

The method area is used to store type information that has been loaded by the virtual machine, constants, static variables, just-in-time compiler compiled code caches, and so on

Type information:

For each loaded type (class, interface, enum, annotation), the JVM must store the following type information in the method area:

  1. The full valid name for this type (full name = package name. The name of the class)
  2. The full valid name of the type’s immediate parent (no parent for interface or Object)
  3. Modifiers of this type
  4. This type is an ordered list of direct interfaces

Domain (FEILD) information:

The JVM keeps information about all the field types of a type and the order in which the fields are declared in the method area

Domain information: Domain name, domain type, and domain modifiers (public, private, protected, static, final, volatile, transient)

Method information:

The JVM holds the following information about all methods, including the order in which they are declared:

  1. Method names
  2. Method return type (or void)
  3. Number and type of method arguments (in order)
  4. Method modifiers (public, private, protected, static, final, synchronized, native, abstract)
  5. Methods bytecode, operand stack, local variable table size (except abstract and native methods)
  6. Exception list (except for abstract and native methods)
    1. The start and end location of each exception handler, the offset address of the code handler in the program counter, and the constant pool index of the caught exception class

Runtime constant pools VS constant pools

The method area contains the run-time constant pool

Bytecode files contain constant pools

The Constant Pool Table in a bytecode file contains various literals and symbolic references to types, fields, and methods

The bytecode file contains references to the constant pool, which is used for dynamic linking

A constant pool can be thought of as a table from which the JVM finds the class name, method name, parameter type, and literal type to execute

The runtime constant pool is dynamic (String.Intern ()), where references are no longer symbolic addresses but real ones

When creating a runtime constant pool for a class or interface, throw OOM if the amount of memory required to construct the runtime constant pool exceeds the maximum that the method area can provide

6. Evolution details of the method area

Changes to the method area in Hotspot:

version Methods area
Jdk1.6 and before There are permanent generations, where static variables are stored
jdk1.7 Persistent generation exists, but has been progressively “de-perpetuated”, string constant pools, static variables removed, and stored in the heap
Jdk1.8 and after No persistent generation. Type information, fields, methods, and constants are stored in the meta space, but the string constant pool and static variables are still in the heap

Permanent substitution space reasons:

  1. It is difficult to set the size of the space for the permanent generation, because the meta-space uses local memory, that is, the size of the meta-space is limited only by local memory
  2. Tuning persistent generations is difficult

7. Method area garbage collection

The Java Virtual Machine specification does not specify this

The GC of the method area is divided into two main parts: obsolete constants in the constant pool and no longer used types

Deprecated constants in the constant pool:

  1. Literals: text strings, constant values declared final, and so on
  2. Symbolic reference:
    1. Fully qualified names of classes and interfaces
    2. The name and descriptor of the field
    3. The name and descriptor of the method

Hotspt’s recycle policy for constant pools: Constants in a constant pool can be recycled as long as they are not referenced anywhere

A type that is no longer in use must meet the following three conditions:

  1. All instances of the class are reclaimed, that is, there are no instances of the class or its subclasses in the heap
  2. The class loader that loads the class is reclaimed, a condition that is often difficult to achieve
  3. The java.lang.Class object corresponding to this Class is not referenced anywhere, and the methods of this Class cannot be accessed anywhere through reflection

8, summary

2.2.6 Runtime constant pool

Part of the method area.

In addition to the Class version, field, method, interface, and other description information, the Class file also contains the constant pool, which is used to store the various literals and symbolic references generated at compile time. This part will go into the runtime constant pool in the method area after the Class is loaded.

Java does not require a constant to be generated only at compile time. That is, the contents of the Class file constant pool can be added to the method area runtime constant pool at run time. For example, the String intern()

The pool is part of the method section, so OutOfMemoryError is also thrown

2.2.7 Direct Memory

Direct memory is not part of the JVM runtime data area, nor is it defined in the JVM specification.

The NIO(New Input/ Output) class introduced in JDK1.4 introduces a channel – and buffer-based I/O approach that uses native libraries to allocate out-of-heap memory directly, and then operates as a reference to that memory through a DirectByteBuffer object stored in the Java heap. It avoids copying data back and forth between the Java heap and Native heap, significantly improving performance.

Consider using direct memory for scenarios with frequent reads and writes

The NIO library allows programs to use direct memory for data buffers

public static void main(String[] args) throws InterruptedException {
        int BUFFER = 1024 * 1024 * 1024 ; // 1G
    	// Allocate local memory space directly
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
        Thread.sleep(100 * 1000);
        byteBuffer = null;
        System.gc();
    }
Copy the code

Native direct memory is not limited by the Java heap size, but is limited by the total native memory (RAM and SWAP or paging file) size and processor addressing space.

Server administrators often ignore direct memory when configuring JVM parameters. The sum of memory regions is greater than the physical memory limit, resulting in OutofMemoryErrors during dynamic expansion

Disadvantages:

Distribution recovery costs are high

It is not managed by JVM memory reclamation

The direct memory size can be set with MaxDirectMemorySize. If not specified, it defaults to the maximum value of the heap, -xmx

java process memory = java heap + native memory


2.3 HotSpot VIRTUAL Machine Object Exploration

2.3.1 Object Creation

  1. The first check is to see if the argument to the directive can locate a symbolic reference to a class in the constant pool, and to see if the class represented by the symbol has been loaded, parsed, and initialized

  2. Allocate memory for newborn objects

    1. The size of the memory required by the object is determined after the class is loaded. When allocating space for objects, the choice of how to have heap memory is disciplined, and whether the heap is disciplined depends on whether the garbage collector used has the ability to compress and collate.

      Pointer collision: Given that the Java heap is perfectly clean, with all used memory on one side and free memory on the other, and a pointer in the middle as an indicator of the dividing point, allocating memory means moving the pointer some distance

      Free list: Heap memory is not tidy, used memory is interlaced with free memory, and the JVM must maintain a list of which memory blocks are available, find a chunk of the list that is large enough to be allocated to object instances at allocation time, and update the list record

    2. You also need to consider whether object creation is a very frequent activity in the JVM. Even simply changing the position of a pointer is not thread-safe in concurrent situations

      1. Synchronizes the action of allocating memory space

      2. The Allocation of memory is allocated to different Spaces by Thread, that is, each Thread allocates a small chunk of memory in the heap (TLAB, Thread Local Allocation Buffer). Whichever thread allocates memory is allocated on the TLAB of the thread, and synchronization locking is only required when the TLAB runs out and new TLabs are allocated

  3. All property Settings set default values to ensure that the instance fields of the object are used directly in the code without assigning initial values

  4. Object header Settings

    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 header.

    How this process is set up depends on the JVM implementation

  5. Execute the init method for initialization

2.3.2 Memory layout of objects

In HotSpot VM, the layout of objects in memory can be divided into object headers, Instance Data, and align Padding.

Object headers include:

1. Store the runtime data of the object itself. Such as hash value, GC generation age, lock status flag, bias thread ID, bias timestamp, etc. This part of data length depends on the number of bits of VM, officially called “Mark Word”. Mark Word reuses storage space based on object state.

2. Type pointer, that is, a pointer to an object’s class metadata that the VM uses to determine which class instance the object is.

3. If the object is an array, the object header contains a chunk of data that records the length of the array.

The instance data portion is the valid information that the object actually stores, as well as the content of various types of fields defined in the code, both inherited and subclassed from the parent class. The order in which this part is stored is affected by the order in which the VM’s default allocation policy parameters and fields are defined in the code.

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

2.3.3 Locating objects

Programs operate specific objects on the heap by reference data on the stack. Currently, there are two mainstream methods:

1. Handle access: a block of memory will be allocated in the heap as the handle pool. Reference stores the handle address of the object, and the handle contains the specific address information of the instance data and type data of the object. The advantage is that reference stores a stable handle address and only changes the power data pointer in the handle when the object is moved, but reference itself does not change

2. Pointer access: The layout of heap objects must consider how to place the information related to the access type data, and the direct storage in reference is the object address. The advantage is that the speed is fast and the time cost of locating pointer is saved.