JVM objects in memory layout?

  In Java programs, we have a variety of ways the new object. In addition to the most common new statement, we can also create new objects by reflection, Object.clone method, deserialization and Unsafe.allocateInstance method.

  Wherein, the Object.clone method and deserialize by direct copying an existing data field to initialize a new instance of the object.

  The method is not initialized Unsafe.allocateInstance instance fields, while the new statement and reflection, is to initialize the instance field by calling the constructor.

  Let's examine the new statement, prepared a class, as shown below

  


  Let him compiled byte code:

  


  Can be seen, new bytecode compiled from statements including instructions for requesting new memory, and an instruction to call the constructor of invokespecial.

  This is not devoted to invoke series of instructions, I will introduce invoke series of instructions in a later article.

  But here I say a mouth, invokespecial bytecode instruction is typically used to call a private instance methods, constructors, and the use of super keyword to call the parent class's instance method or constructor, the default interface method and implemented.

  Mentioned constructor, you have to mention the many constraints on Java constructor. First, if a class does not define any constructors, then, Java compiler will automatically add a constructor with no arguments.

  We just TestNew class, he bytecode compiler, there are the following fragment.

  


  In JAVA source code, we do not define a constructor, but it generates bytecode, has helped us to automatically add a constructor with no arguments. invokespecial method he uses is the final call its parent class constructor method of the Object class.

  I will tell JVM constructor calls the principle that, if a subclass constructor needs to call the constructor of the parent class. If a parent class exists, then no argument to the constructor, the call may be implicit. In other words, Java compiler will automatically add the call to the parent class constructor.

  However, if no parent class constructor without parameters, then the subclass constructor will need to explicitly call parent class constructor parameters.

  Explicit call, there are two, one is the direct use of "super" to call the parent class constructor keyword, the second is to use "this" keyword call another constructor of the same class.

  Whether direct explicit call, or indirectly explicit call, you need to first statement as a constructor to initialize the parent class priority field is inherited.

  Priority can not initialize inherited parent class field? Yes, if you can use bytecode injection tool words.

  When we call a constructor, it takes precedence call the constructor of the parent class, until the Object class. Both of these calls the constructor for the same object, that is, by the new directive from the new object.

  In fact, my above statement means: New out by the new command object, its memory is actually covers all instance fields in the parent class.

  In other words, although the subclass can not access the parent class's private instance field or instance field subclass hides the parent class instance fields of the same name, but the instance of a subclass of these parent classes will still memory allocated for the instance fields.

  Now I will introduce pointer compression technology. In the Java virtual machine, Java each object has an object header, which is constituted by a tag field and a pointer type.

  Tag field for storing a Java virtual machine operating data about the object, such as a hash code, and the GC information lock information, and the type of a pointer points to the object class.

  In the JVM 64, the header tag field representing the object 64, and they account for the type of 64-bit pointer. That is, each Java object in memory overhead is 16 bytes.

  To minimize memory usage small object, JVM introduced the concept of 64-bit pointer compression, the original 64-bit stack pointer to Java objects compressed into 32 bits.

  Thus, the type of the object header pointer will be compressed to 32 bits, so that the size of the object header from 16 bytes to 12 bytes.

  Of course, the pointer can not only act on the compression type index object header, the reference may also be applied to the type of field, and a reference to an array type.

  What is the principle? The answer is memory alignment.

  We require, by default, the start address JVM heap objects need to be aligned to a multiple of 8, if an object is less than 8N bytes, so that part of the blank space is wasted, which we wasted space filled between objects referred to.

  As we all know, which is the address of the pointer, since the start address when the object on the heap are aligned to a multiple of 8, so that a reference pointer store (or object class) of the memory address, there is no need to store the last three binary number.

  Because all objects or classes are aligned memory addresses 8, so their lowest three bits of the memory address pointer is always 0,32 can be addressed byte to 35-th power of 2, the address space is 32GB (over 32GB will turn off compression pointer).

  We can further enhance the addressing range by configuring virtual machine memory alignment options. But it also may increase the filling between objects, resulting in compression pointer did not reach the original space-saving effect.

  Even if you turn off the compression pointer, Java virtual machine memory will still be aligned. Further, not only in memory alignment between the object and the object, it is also present between the object field.

  For example, Java Virtual Machine requires long field, double field, and the non-compressed field of the address pointer reference state is a multiple of 8.

  Why is this?

  The CPU cache line mechanism we should have heard, if the field is not aligned, then there is a field across a cache line may occur.

  This field is read two cache lines may need to be replaced, and storing the field will also contaminated two cache lines.

  We will process about the volatile nature of the latter article keyword analysis, to re-examine the mechanisms CPU cache line.

  Finally, I want to mention that that the field rearrangement technique that I just mentioned, there is an object between the fields of memory alignment. This means that in order to re-allocation field, for the purpose of memory alignment

  It has the following two rules:

  First, if a field C occupies bytes, then the offset of the field need to be aligned to the NC. Here the offset difference refers to a start address of the address field of the object.

  In Case of Long, it is only one instance field type long. Using a 64-bit pointer compression virtual machine, although the size of the object header is 12 bytes, the offset of the long type field can only be 16, and the intermediate empty four bytes is wasted fall

  Second offset field, subclasses inherit parent class should be mapped to an offset field consistent.

  Plainly, such as B inherits A, A is the parent of B, and A in all fields, in B has, and is the first release of Field A, B, came alive again in the field. Class B and Class A discharge object field, you need to be consistent with the offset field corresponding to the parent class.

  Then I said to expand the contents of a bar, what is a virtual shared?

  Suppose two threads are accessing the same object in different volatile field, they are not logically shared content, and therefore need not be synchronized.

  If these two fields are exactly in the same cache line, then write to these fields will lead to write-back cache line, also resulted in a substantial share.

  Java8 also introduces a new annotation @Contended, to solve shared among virtual object fields.

  Java virtual machines allow different @Contended field is independent of the cache line, so you will see a lot of space is wasted, avoid unnecessary cache line synchronization.

  Specific algorithm is an implementation detail, and we are interested can go with:

  -XX:-RestrictContended

  The virtual machine options, view memory layout Contended field.


Reproduced in: https: //juejin.im/post/5cee2d55f265da1b94212bb1

Guess you like

Origin blog.csdn.net/weixin_33720956/article/details/91435547