The JVM Self-study Guide has been compiled into my GitHub open source project: [JVM Self-Study Guide]

Object’s instantiated memory layout and access location + direct memory

1. Object instantiation

1. How objects are created

  • new
    • The most common way
    • Deformation 1: static method of Xxx
    • Morphing 2: Static methods for XxBuilder/XxoxFactory
  • Class newInstance () : this is a reflection of the constructor that can only be called with null arguments. The permission must be public
  • Constructor newInstance (Xxx) : this is a reflection of a Constructor that can be called with empty or arguments. Permissions are not required
  • Using Clone () : Without calling any constructor, the current class needs to implement the Cloneable interface to implement Clone ()
  • Use deserialization: Get a binary stream of an object from a file, from the network
  • The third-party library Objenesis

2. Steps to create an object

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

    Check whether there is a symbolic reference to the class in the constant pool of the meta space, and check whether the link initialization is loaded.

    • If so, the corresponding Class file is generated.

    • If not, in the parent delegation mode, use the current class to find the corresponding. Class file with [ClassLoader+ package name + class name] as the Key.

      • If found, it is loaded and the corresponding Class file is generated.
      • If not, a ClassNotFoundException is thrown
  2. Allocate memory for an object

    1. The size of the object is calculated and the corresponding bytes are allocated in the heap. If the instance variable is a reference variable, only 4 bytes are allocated.
    • If memory is neat: pointer collision

      • With all the used memory on one side and the free memory on the other, and a pointer in the middle as an indicator of the dividing point, allocating memory is simply a matter of moving the pointer to the free side by a distance equal to the size of the object. If the garbage collector selects Serial and ParNew, which are based on compression algorithms, the virtual machine uses this allocation mode. Pointer collisions are typically used when using a collector with a compact procedure.
    • If memory is irregular: free list

      • If memory is not structured, with used and unused memory interleaved, then the VIRTUAL machine will use the free list method to allocate memory for objects. This means that the VIRTUAL machine maintains a list of which memory blocks are available, finds a large enough chunk of the list to allocate to the object instance, and updates the list. This is called a “Free List.”
    • Note: The choice of which allocation method is determined by whether the Java heap is neat, which in turn is determined by whether the garbage collector is used with compression.

    • Assignment to an object’s properties takes place in the following order: (1) default initialization of the property (2) explicit/block initialization (whoever comes first) (3) constructor initialization

  3. Handle concurrency security issues

    1. Compare And Swap (CAS) failure retry And region lock: ensure the atomicity of pointer update operations.
    2. TLAB allocates memory in different Spaces according to threads, that is, each Thread preallocates a small piece of memory in the Eden area of the Java heap, called the Local Thread Allocation Buffer. It can be set with a XX: +UseTLAB parameter.
  4. Initialize the allocated space

    After memory allocation is complete, the VM initializes the allocated memory space to zero. This step ensures that the instance fields of the object can be used in Java code without having to assign an initial value, and that the program can access the zero value corresponding to the data type of these fields.

  5. Sets the object header for the object

    The owning class of the object (that is, the metadata information of the class), the HashCode of the object, the GC information of the object, the lock information, and other data are stored in the object header of the object. How this process is set up depends on the JVM implementation.

  6. Execute the init method to initialize

    From the perspective of a Java program, initialization officially begins. Initialize the member variable, execute the instantiation block, call the class constructor, and assign the first address of the object in the heap to the reference variable. So in general (depending on whether the invokespecial directive is followed in bytecode), the new directive is followed by the execution method, which initializes the object as the programmer intended, so that a truly usable object is fully created.

Load class meta information – “Allocate memory for an object -” Handle concurrency issues – “Default initialization of properties -” Set object headers – “init method

Second, the memory layout of the object

1. Object headers

  • Runtime metadata
    • HashCode
    • GC generation age
    • Lock status flag
    • A lock held by a thread
    • Biased thread ID
    • Biased timestamp
  • Type pointer: An InstanceKlass that points to the class metadata to determine the type to which the object belongs

Note: If it is an array, record the length of the array

2. Instance data

This is the valid information that the object actually stores, including rules for the various types of fields defined in the program code (including fields inherited from the parent class and owned by itself) :

  • Fields of the same width are always assigned together
  • Variables defined in the parent class appear before the child class
  • If the CompactFields argument is true (the default is true), a narrow variable of a subclass may be inserted into the gap between the variables of the parent class

3, filling

It’s not required, it has no meaning, it’s just a placeholder

4, summary

public class CustomerTest {
    public static void main(String[] args) {
        Customer cust = newCustomer(); }}Copy the code

3. Object access location

JVM is thought to be | how to through the object in the stack frame with access to the interior of the object instance? -> locate, accessed by reference on the stack

There are two main ways to access objects

  • Handle access

    • Disadvantages: Low efficiency, need to open up special space to store Pointers

    • Advantages: relatively stable, when the pointer is changed, the reference in the stack frame does not need to change, only the corresponding heap handle pool can be changed.

  • Direct pointer (HotSpot uses)

Direct memory

  • It is not part of the data area when the VIRTUAL machine is running, nor is it a memory area defined in the Java Virtual Machine Specification

  • Direct memory is the amount of memory outside the Java heap that is applied directly to the system

/** * IO NIO (New IO/non-blocking IO) * byte[] / char[] Buffer * Stream Channel **
 public class BufferTest {
    private static final int BUFFER = 1024 * 1024 * 1024;//1GB

    public static void main(String[] args){
        // Allocate local memory space directly
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
        System.out.println("Direct memory allocated, request instructions!");

        Scanner scanner = new Scanner(System.in);
        scanner.next();
     
        System.out.println("Direct memory freeing!");
        byteBuffer = null; System.gc(); scanner.next(); }}Copy the code
  • From NIO (new I/O after 1.7), local memory is operated by DirectByteBuffer that exists in the heap

    • I/O Reads files

    • NI/O Reads files

    • In general, direct memory access is faster than the Java heap. That is, high read/write performance

      • Therefore, for performance reasons, direct memory may be considered in high read/write situations
      • Java’s NIO library allows Java programs to use direct memory for data buffers

      OutOfMemoryError: indicates Direct buffer memory

      Since direct memory exists outside the Java heap, its size is not directly limited to the maximum heap size specified by Xmx, but system memory is limited, and the sum of the Java heap and direct memory is still limited to the maximum memory that the operating system can give.

      • = = = = shortcomings
        • Allocation recovery costs are higher
        • Not managed by JVM memory reclamation

      The direct memory size can be set with MaxDirectMemorySize

      If not specified, the default value is the same as the maximum value of the heap Xmx parameter

      Memory used by Java processes = Java heap + Local direct memory