In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
In this issue, the editor will bring you an example analysis of HotSpot virtual machine objects in Java technology JVM research. The article is rich in content and analyzes and narrates it from a professional point of view. I hope you can get something after reading this article.
Creation of object
At the language level, creating objects (exceptions: cloning, deserialization) is usually just a new keyword, but in a virtual machine, what is the process of creating objects (the objects discussed in this article are limited to ordinary Java objects, excluding arrays, Class objects, etc.)?
When the virtual machine encounters a new instruction, it will first check whether the parameters of the instruction can locate a symbolic reference to a class in the constant pool, and check whether the symbolic reference represents a class that has been loaded, parsed, and initialized. If not, you must first perform the corresponding class loading process.
Allocation of memory
After the class is loaded, the virtual machine then allocates memory for the new object. The amount of memory required for an object can be fully determined after the class is loaded (how to determine that it will be explained in detail in the next section of the object memory layout). The task of allocating space for an object is tantamount to a certain size of memory divided from the Java heap.
Pointer collision
Assuming that the memory in the Java heap is absolutely regular, all used memory is put on one side, and the free memory is placed on the other side, with a pointer in the middle as an indicator of the demarcation point, then the allocated memory simply moves the pointer to the free space for a distance equal to the size of the object, which is called "pointer Bump The Pointer".
Free list
The memory in the Java heap is not regular, and the used memory and free memory are interlaced with each other, so there is no way to simply carry out pointer collisions. The virtual machine must maintain a list, record which memory blocks are available, find a large enough space from the list to allocate to object instances, and update the records on the list. This allocation method is called "free list" (Free List).
Memory allocation selection
The choice of allocation method is determined by whether the Java heap is neat or not, and whether the Java heap is neat or not is determined by whether the garbage collector used has the compression function. Therefore, when using collectors with Compact procedures such as Serial and ParNew, the allocation algorithm adopted by the system is pointer collisions, while when using collectors based on Mark-Sweep algorithm such as CMS (to illustrate that CMS collectors can organize memory through UseCMSCompactAtFullCollection or CMSFullGCsBeforeCompaction), free lists are usually used.
Memory allocation problem
In addition to how to divide the available space, another problem to consider is that object creation is very frequent in the virtual machine, even if it is only to modify the location pointed to by a pointer, it is not thread-safe in the case of concurrency. Object A may be allocating memory to object A, and the pointer has not yet been modified, and object B uses the original pointer to allocate memory at the same time. * * there are two solutions to this problem. One is to synchronize the actions of allocating memory space-in fact, the virtual machine uses CAS with failed retry to ensure the atomicity of the update operation. The other is to divide the memory allocation into different spaces according to threads, that is, each thread pre-allocates a small piece of memory in the Java heap, which is called local thread allocation buffer, (TLAB, Thread Local Allocation Buffer), which thread allocates memory on the TLAB of which thread, only when TLAB is used up, new TLAB allocation needs synchronous locking. Whether the virtual machine uses TLAB or not can be set by the-XX:+/-UseTLAB parameter. After the memory allocation is completed, the virtual machine needs to initialize the allocated memory space to zero (excluding object headers), which can also be advanced to TLAB allocation if TLAB is used. This operation ensures that the instance fields of the object can be used directly in the Java code without assigning initial values, and the program can access the zero values corresponding to the data types of these fields.
Object header parameter configuration
The virtual machine needs to set the necessary information on the object, such as which class the object is, how to find the metadata information of the class, the hash code of the object, the GC generation age of the object and so on. This information is stored in the object's Object Header. Depending on the current running state of the virtual machine, such as whether to enable bias locks, the object header will be set in different ways.
From a virtual machine perspective, a new object has been created. From the perspective of the Java program, object creation is just beginning-- the method hasn't been executed yet, and all the fields are zero. So generally speaking (depending on whether the bytecode is followed by an invokespecial instruction), the new instruction is followed by the execution of the method, initializing the object according to the wishes of the programmer, so that a truly available object is fully generated.
The following code is a snippet from the HotSpot virtual machine bytecodeInterpreter.cpp. (this interpreter implementation is rarely used in practice, and a template interpreter is used on most platforms; the difference is even greater when the code is executed through the JIT compiler. However, there is no problem with this code to understand how HotSpot works.
/ / make sure that the constant pool holds the interpreted class if (! constants- > tag_at (index). Is_unresolved_klass ()) {/ / assertion ensures that it is klassOop and instanceKlassOop (described in the next section of this section) oop entry = (klassOop) * constants- > obj_at_addr (index); assert (entry- > is_klass (), "Should be resolved klass"); klassOop k_entry = (klassOop) entry Assert (knight entry-> klass_part ()-> oop_is_instance (), "Should be instanceKlass"); instanceKlass* ik = (instanceKlass*) knight entry-> klass_part (); / / make sure that the type to which the object belongs has gone through the initialization phase if (ik- > is_initialized () & & ik- > can_be_fastpath_allocated ()) {/ / fetch the object length size_t obj_size = ik- > size_helper () Oop result = NULL; / / record whether all fields of the object need to be zeroed bool need_zero =! ZeroTLAB; / / whether to assign the object if (UseTLAB) {result = (oop) THREAD- > tlab (). Allocate (obj_size);} if (result = = NULL) {need_zero = true / / assign the object retry directly in eden: HeapWord* compare_to = * Universe::heap ()-> top_addr (); HeapWord* new_top = compare_to + obj_size / / cmpxchg is the CAS instruction in x86. Here is a C++ method that allocates space through CAS and concurrently fails. Go to retry and retry until if (new_top end_addr ()) {if (Atomic::cmpxchg_ptr (new_top, Universe::heap ()-> top_addr (), compare_to)! = compare_to) {goto retry } result = (oop) compare_to;}} if (result! = NULL) {/ / initialize zero value if (need_zero) {HeapWord* to_zero = (HeapWord*) result + sizeof (oopDesc) / oopSize for the object if necessary Obj_size-= sizeof (oopDesc) / oopSize; if (obj_size > 0) {memset (to_zero, 0, obj_size * HeapWordSize) }} / / set object header information if (UseBiasedLocking) {result- > set_mark (ik- > prototype_header ());} else {result- > set_mark (markOopDesc::prototype ());} result- > set_klass_gap (0) depending on whether bias lock is enabled Result- > set_klass (k_entry); / / reference the object to the stack and continue to execute the next instruction SET_STACK_OBJECT (result, 0); UPDATE_PC_AND_TOS_AND_CONTINUE (3,1);} object memory layout
In a HotSpot virtual machine, the layout of objects stored in memory can be divided into three areas: object headers (Header), instance data (Instance Data), and alignment padding (Padding).
The object header of the HotSpot virtual machine consists of two parts of information. The first part is used to store the runtime data of the object itself, such as HashCode, GC generational age, lock status flag, lock held by thread, biased thread ID, biased timestamp, and so on. The length of this part of data is 32 and 64 Bits respectively in 32-bit and 64-bit virtual machines (scenarios where the compression pointer is not considered for the time being), which is officially called "Mark Word".
Objects need to store a lot of run-time data, in fact, it has exceeded the limit that 32-bit and 64-bit Bitmap structure can record, but object header information is an additional storage cost independent of the data defined by the object itself. Considering the space efficiency of the virtual machine, Mark Word is designed as a non-fixed data structure to store as much information as possible in a very small space. It will reuse its own storage space according to the state of the object. For example, when objects are not locked in a 32-bit HotSpot virtual machine, 25Bits in 32 Bits spaces of Mark Word is used to store object hash codes (HashCode), 4Bits is used to store object generations, 2Bits is used to store lock flag bits, and 1Bit is fixed to 0. The storage contents of objects in other states (lightweight locking, heavyweight locking, GC marking, biasing) are shown in the following table.
Virtual machine object header | Type | 32-bit JVM | 64-bit JVM |-| markword | 32bit | 64bit | | Type pointer | 32bit | 64bit, 32bit when pointer compression is enabled | | Array length | 32bit | 32bit | |
When pointer compression is enabled, markword occupies 8bytes, type pointer occupies 8bytes, and altogether occupies 16bytes
When pointer compression is not enabled, markword occupies 8bytes and type pointer occupies 4bytes, but since the java memory address is aligned according to 8bytes, the length must be a multiple of 8, so it will be completed from 12bytes to 16bytes
The array length is 4bytes, which is also aligned and complemented to 8bytes.
If the object does not override the hashcode method, the default is to call os::random to generate hashcode, which can be obtained through System.identityHashCode; os::random produces
The rule of hashcode is: next_rand = (16807seed) mod (2x31-1), so 31-bit storage can be used; in addition, once a hashcode,JVM is generated, it will be recorded in markword
GC age is stored in 4-bit bit, with a maximum of 15. For example, the default value of MaxTenuringThreshold parameter is 15.
When in a lightweight lock or a heavyweight lock, the recorded object pointer is considered to be 64-bit according to JVM, and the lowest two bits are assumed to be 0. when in a bias lock, the recorded thread pointer is also 64-bit.
Tag field 32 bits: hash:25-> | age:4 biased_lock:1 lock:2 (normal object) JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object) size:32-- > | (CMS free block) PromotedObject*: 29-> | promo_bits:3-> | (CMS promoted object) 64 bits: unused:25 hash:31-- > | unused:1 age:4 biased_lock:1 lock:2 (normal object) JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object) PromotedObject*:61-> | promo_bits: 3-> | (CMS promoted object) size:64-- > | (CMS free block) unused:25 hash:31-- > | cms_free:1 age:4 biased_lock:1 lock:2 (COOPs & & normal object) JavaThread*:54 epoch:2 cms_free:1 Age:4 biased_lock:1 lock:2 (COOPs & & biased object) narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3-> | (COOPs & & CMS promoted object) unused:21 size:35-- > | cms_free:1 unused:7-> | (COOPs & & CMS free block) type pointer
The other part of the object header is the type pointer, which is the pointer of the object to its class metadata, through which the virtual machine determines which class the object is an instance of. Not all virtual machine implementations have to retain type pointers on object data, in other words, finding metadata information about an object does not have to go through the object itself, which we discuss in the next section. In addition, if the object is a Java array, there must be a piece of data in the object header to record the length of the array, because the virtual machine can determine the size of the Java object through the metadata information of the ordinary Java object, but the size of the array cannot be determined from the metadata of the array.
The following is a code (comment) snippet from the HotSpot virtual machine markOop.cpp, which describes the storage state of MarkWord under 32bits:
Instance data
Next, the instance data part is the valid information really stored by the object, and it is also the various types of field content that we define in the program code, whether inherited from the parent class or defined in the subclass.
The storage order of this part is affected by the virtual machine allocation policy parameters (FieldsAllocationStyle) and the order in which the fields are defined in the Java source code.
The default allocation policies for HotSpot virtual machines are longs/doubles, ints, shorts/chars, bytes/booleans, oops (Ordinary Object Pointers). As you can see from the allocation policy, fields of the same width are always assigned together. If this prerequisite is met, the variables defined in the parent class will appear before the subclass. If the CompactFields parameter value is true (the default is true), narrower variables in the subclass may also be inserted into the gaps in the parent variable.
Align fill
Alignment padding is not inevitable, nor does it have any special meaning, it just acts as a placeholder.
Because HotSpot VM's automatic memory management system requires that the starting address of the object must be an integral multiple of 8 bytes, in other words, the size of the object must be an integral multiple of 8 bytes. The header of the object is exactly a multiple of 8 bytes (1 or 2 times), so when the data part of the object instance is not aligned, it needs to be filled with alignment padding.
Access location of object
Objects are created in order to use objects, and our Java program needs to manipulate specific objects on the heap through the reference data on the stack. Because the reference type only specifies a reference to the object in the Java virtual machine specification, it does not define how the reference should locate and access the specific location of the object in the heap, and the object access mode also depends on the implementation of the virtual machine. The mainstream access methods are using handles and direct pointers.
If you use handle access, a piece of memory will be divided in the Java heap to serve as a handle pool. What is stored in reference is the handle address of the object, and the handle contains the specific address information of the object instance data and the type data. As shown in figure 1.
If direct pointer access is used, the layout of the Java heap object must consider how to place information about the access type data, and the object address is directly stored in the reference, as shown in figure 2.
These two kinds of object access methods have their own advantages. The biggest advantage of using handles to access is that the address of the stable handle is stored in reference. When the object is moved (moving the object when garbage collection is a very common behavior), only the instance data pointer in the handle will be changed, while the reference itself does not need to be modified.
The biggest advantage of using direct pointer to access is faster, it saves the time overhead of pointer positioning, because object access is very frequent in Java, so this kind of overhead product is much smaller is also a very considerable implementation cost. From the object memory layout explained in the previous section, we can see that as far as virtual machine HotSpot is concerned, it uses the second way to access objects, but in the whole scope of software development, it is also very common to use handles in various languages and frameworks.
The above is the example analysis of the HotSpot virtual machine object in the Java technology JVM research shared by the editor. If you happen to have similar doubts, please refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.