HotSpot virtual machine object exploration (6)

Object creation
  • When the virtual machine encounters a new instruction, it first checks whether the parameter of this instruction can locate a symbol reference of a class in the constant pool, and checks whether the class represented by this symbol reference has been loaded, resolved, and initialized. If not then first execute the corresponding class loading process.

  • After the class loading check is passed, the virtual machine then needs to allocate memory for the new objects. The required memory size of the object can be completely determined after the class loading is completed. The task of allocating memory for the object is equivalent to dividing a certain size of memory from the java heap. Assuming that the Java heap memory is completely 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 an indicator of the demarcation point. This allocation method becomes " 指针碰撞". If the java heap space is not regular, the used memory and free memory are intersected with each other, then there is no way to simply use pointer collision, the virtual machine must maintain a list to record which memory is available, when allocating memory Find a large enough space for the object from the list, and update the record on the list. This allocation method becomes " 空闲列表". The choice of the allocation method is determined by whether the Java heap is regular, and whether the Java heap is regular is determined by whether the garbage collector used has a compression and sorting function. Therefore, collectors with Compact processes such as Serial and ParNew use pointer collision, while collectors based on Mark-Sweep algorithm such as CMS usually use free lists.

  • In addition to the division of available space, the creation of objects in the virtual machine is a very frequent behavior. Even if only the location of a pointer is modified, it is not thread-safe in concurrent scenarios. It may be allocating the memory required by the A object. , The pointer has not had time to modify the pointer, object B also uses the original pointer to allocate memory. There are two solutions to solve this problem: one is that the object allocates memory space for synchronization processing-the actual use of CAS with a failed retry mechanism to ensure the atomicity of the update operation; the other is to assign the memory allocation action according to the thread The division is performed in different spaces, that is, each thread allocates a piece of memory in the Java heap in advance and becomes 本地线程分配缓冲(Thread Local Allocate Buffer,TLAB). Which thread needs to allocate memory is allocated on the TLAB of which thread. Only when the TLAB is used up and redistributed, it is necessary to determine synchronously whether the virtual machine uses TLAB or not, which can be -XX: +/- UseTLABset by parameter parameters.

    TLAB:
    TLAB avoids multi-thread conflicts. When allocating memory to an object, each thread uses its own TLAB, which avoids thread synchronization and improves the efficiency of object allocation. TLAB itself occupies space in the eEden area. With TLAB turned on, the virtual machine allocates a TLAB space for each Java thread. The parameter -XX: + UseTLAB enables TLAB. The JVM is enabled by default. The memory of the TLAB space is very small. By default, it only occupies 1% of the entire Eden space. You can set the EDEN space occupied by the TLAB space through the option -XX: TLABWasteTargetPercent The percentage size. TLAB space is generally not very large, so large objects cannot be allocated on TLAB, and are always allocated directly on the heap. Because the TLAB space is relatively small, it is easy to fill up. For example, a 100K space has already used 80KB, and when a 30KB object needs to be allocated, it will certainly be powerless. At this time, the virtual machine has two options. First, the current TLAB is discarded, so that 20KB of space is wasted; second, the 30KB object is directly allocated on the heap, and the current TLAB is retained, so that you can hope that there will be less than 20KB in the future. Object allocation requests can use this space directly. In fact, a value called refill_waste is maintained inside the virtual machine. When the requested object is greater than refill_waste, it will choose to allocate in the heap. If it is less than this value, the current TLAB will be discarded and a new TLAB will be created to allocate the object. This threshold can be adjusted using TLABRefillWasteFraction, which represents the proportion of such waste allowed in TLAB. The default value is 64, which means that about 1/64 of TLAB space is used as refill_waste. By default, TLAB and refill_waste will be continuously adjusted at runtime to optimize the system's operating state. If you want to disable the automatic adjustment of the size of TLAB, you can use -XX: -ResizeTLAB to disable ResizeTLAB, and use -XX: TLABSize to manually specify the size of a TLAB. -XX: + PrintTLAB can track the usage of TLAB. It is generally not recommended to manually modify TLAB related parameters, it is recommended to use the default behavior of the virtual machine.

  • Next, the virtual machine needs to set the necessary parameters of the object, such as which class instance of the object, how to find the meta information of the class, the hash code of the object, and the GC generation age of the object. These information will be set in the head of the object ( Object Header)

  • After the above work is completed, a new object is created from the perspective of the virtual machine. From the perspective of java, object creation has just begun-the <init> method has not been executed, and all fields are still 0, so execute new After the command is initialized according to the programmer's wishes, a truly usable object is calculated.

Object memory allocation flowchart
  • Class loading and memory allocation process
    Class loading and memory allocation process
  • Flow chart of object allocation in heap memory
    Flow chart of object allocation in heap memory
Object memory layout

In HotSpot virtual machine, objects stored in memory to find the layout may be divided into three regions: 对象头(Hesder), 实例数据(Instance)and 对其填充(Padding).

  • 对象头:The header information mainly includes two parts. The first part is the user's runtime data such as hash code (HashCode), GC generation age, lock status flag, lock held by the thread, biased thread ID, biased timestamp, etc. The length of some data is 32bit and 64bit in 32-bit and 64-bit virtual machines (without pointer compression enabled), respectively. Officially called it "Mark word". Objects need to store a lot of runtime data, in fact, it has exceeded the limit of 32-bit and 64-bit Bitmap structures that can be recorded, but the object header information is extra storage cost independent of the data defined by the object itself, considering the space of the virtual machine Efficiency, Mark Word is designed as a non-fixed-length data structure in order to store as much information as possible in a very small space, it will reuse its storage space according to the state of the object. The other part is the type pointer, that is, the pointer of the object to his class metadata. The virtual machine uses this pointer to determine the instance of the class of the object. Not all virtual machine implementations must retain the type pointer on the object data. In other words, finding metadata information of an object does not necessarily go through the object itself. If the object is an array, then the object header must also have a piece of data used to record the length of the array.
    Mark Word stores different content under different lock states, so it is stored in the 32-bit JVM:
    Object header information
  • 实例数据:It is the effective information that the object really stores, and also the various types of field content defined in the program code. Whether it is inherited from the parent class or defined by the subclass, it needs to be recorded. The storage order of this part will be affected by the order of the virtual machine's allocation strategy parameters (FiledsAllocationStype) and fields defined in the Java source code. HotSpot's allocation strategy is longs / doubles, ints, shorts / char, bytes, booleans, oops (Ordinary Object Pointers). As can be seen from the allocation strategy, fields of the same width will be allocated together, under the premise of meeting this condition , Variables defined in the parent class will also appear before the child class. If the CompactFields parameter value is true (the default is true), then narrower variables in subclasses may also be inserted into the gaps of categorical variables.
  • 对象填充:Object padding does not necessarily exist and has no special meaning, it is just a placeholder. Mainly because the HotSpot JVM memory management system requires that the object start address must be an integer multiple of 8, that is, the object size must be an integer multiple of 8, and the object header part is exactly an integer multiple of 8 (1 times or 2 times), so the object If the instance data part is not aligned, it needs to be completed by filling.
Object access positioning

The object is created mainly to use the object. Our Java program mainly uses the Reference data on the stack to operate the specific object on the heap. The Reference only specifies a reference to the object, and does not define how the reference object is located. And access to the specific location of objects on the heap, so object access depends on the virtual machine's own implementation. The main methods of mainstream 句柄and 直接指针.

  • 句柄访问: Using handle access, the Java heap will be divided into a memory as a handle pool. The reference is stored in the handle pool of the object, and the handle pool contains the specific address information of the object instance data and data type as shown in the figure:
    Handle access
  • 直接指针:When using direct pointer access, the layout of the Java heap object must consider how to place relevant information about access type data, and the address stored directly in the Reference is the object address, as shown in the figure:
    Direct pointer

The advantages and disadvantages of handle access and direct pointer access: The biggest advantage of
using 句柄is that the reference is stored in the implicit handle address, when the object is moved (moving objects during garbage collection is a very common behavior), only the instance in the handle will be changed Data pointer, and Reference itself does not need to be modified. 直接指针The biggest advantage is fast speed, which saves the pointer positioning overhead. Because the access of objects is very frequent in Java, the accumulation of such overhead is also a considerable execution cost. The Sun HotSpot virtual machine mainly uses
direct pointers to access objects. From the perspective of the overall software development scope, it is also very common for various languages ​​and frameworks to use handle access.

Insert picture description here

Published 41 original articles · Liked 14 · Visitors 10,000+

Guess you like

Origin blog.csdn.net/Yunwei_Zheng/article/details/105171632