Baidu Daniel teaches you the necessary skills for interviews in Java new Object...

This article mainly introduces the interviewer: new Object() in Java occupies a few bytes in the end. This article introduces you in detail, which has a certain reference value for everyone's study or work. Friends who need it can refer to it.

Let's analyze the layout of the heap and the layout of Java objects in memory.

Pointing to the object *
Look at a piece of code first:

package com.zwx.jvm;
 
public class HeapMemory {
    
    
  private Object obj1 = new Object();
 
  public static void main(String[] args) {
    
    
    Object obj2 = new Object();
  }
}

In the above code, what is the difference between obj1 and obj2 in memory?

Let's recall that in the article of JVM series 1, it is mentioned that the method area stores the structure of each class, such as runtime constant pool, attribute and method data, as well as data such as methods and constructors. So our obj1 has a method area, and new will create an object instance, which is stored in the heap, so there is the following picture (the method area points to the heap):

Insert picture description here

Obj2 is a local variable in the method, which is stored in the local variable table in the stack frame in the Java virtual machine stack. This is the classic stack pointer to the heap:
Insert picture description here

Here we come to think again, we have a variable pointing to the heap, and only an instance object is stored in the heap, then how does the sample object in the heap know which Class it belongs to, that is to say, how does this instance know its corresponding class? What about meta-information? This involves how a Java object is laid out in memory.

Java memory model

The object memory can be divided into three areas: object header (Header), instance data (Instance Data) and alignment padding (Padding). Take the 64-bit operating system as an example (when pointer compression is not turned on), the Java object layout is shown in the figure below Show:

Insert picture description here

The detailed information in the Mark Word in the object header is described in detail in the article Synchronized Lock Upgrade Principle. The alignment padding in the above figure is not necessarily there. If the object header and instance data add up to a multiple of 8 bytes, then alignment padding is not required.
Know the Java memory layout, then let's look at an interview question

Object obj=new Object()占用字节

This is a problem that many people on the Internet will mention. Then combined with the Java memory layout above, let’s analyze it. Taking a 64-bit operating system as an example, the new Object() occupancy size is divided into two situations:

-Pointer compression is not enabled and the occupied size is: 8 (Mark Word) + 8 (Class Pointer) = 16 bytes
-Pointer compression is enabled (default is enabled) After pointer compression is enabled, Class Pointer will be compressed to 4 bytes. The final size is: 8 (Mark Word) + 4 (Class Pointer) + 4 (aligned padding) = 16 bytes.
Is this the result? Let's verify it. First introduce a pom dependency:

<dependency>
      <groupId>org.openjdk.jol</groupId>
      <artifactId>jol-core</artifactId>
      <version>0.10</version>
    </dependency>
   

Then create a simple demo:

package com.zwx.jvm;
 
import org.openjdk.jol.info.ClassLayout;
 
public class HeapMemory {
    
    
  public static void main(String[] args) {
    
    
    Object obj = new Object();
    System.out.println(ClassLayout.parseInstance(obj).toPrintable());
  }
}

The output is as follows:

The final result is 16 bytes, no problem. This is because pointer compression is turned on by default, so let's try again after turning off pointer compression.

-XX:+UseCompressedOops turn on pointer compression
-XX:-UseCompressedOops turn off pointer compression

Insert picture description here

Run again and get the following results:
Insert picture description here

As you can see, there is no alignment and padding part at this time, but the occupied size is still 16 bits.

Let's demonstrate the size of an object with attributes below.

Create a new class with only one byte attribute inside:

package com.zwx.jvm;
 
public class MyItem {
    
    
  byte i = 0;
}

Then respectively output the size of this class in the scenes of turning on pointer compression and turning off pointer compression.

package com.zwx.jvm;
 
import org.openjdk.jol.info.ClassLayout;
 
public class HeapMemory {
    
    
  public static void main(String[] args) {
    
    
    MyItem myItem = new MyItem();
    System.out.println(ClassLayout.parseInstance(myItem).toPrintable());
  }
}

Turn on pointer compression, occupying 16 bytes:
Insert picture description here

Turn off pointer compression, occupying 24 bytes:
Insert picture description here

At this time, it can be seen that the advantages of pointer compression are turned on. If a large number of objects are created continuously, pointer compression will still optimize performance to a certain extent.

Object access After
creating an object, of course we need to access it. So when we need to access an object, how do we locate the object? At present, there are two main ways to access objects: handle access and direct pointer access.

Handle access uses handle access, the Java virtual machine divides a memory in the heap to store the handle pool, then the handle address is stored in the object, and then the object instance data and object type data address are stored in the handle pool.
Insert picture description here

Direct pointer access (the method used by the Hot Spot virtual machine) Direct pointer access will directly store the object type data in the object.

Insert picture description here

Comparison of handle access and direct pointer access. In the
figure above, we can easily compare, that is, if you use handle access, there will be one more pointer positioning, but it also has the advantage that if an object is moved (the address is changed), then only You only need to change the pointer of the handle pool, you don't need to modify the pointer in the reference object, and if you use direct pointer access, you need to modify the reference pointer in the local variable table.

Heap memory As
we mentioned above, the Mark Word in the Java object header stores the generational age of the object, so what is the generational age?

The generational age of an object can be understood as the number of garbage collections. When an object still exists after a garbage collection, the generational age will increase by 1. In a 64-bit virtual machine, the generational age occupies 4 places, the largest The value is 15. The default generation age is 0000, and it will gradually increase with the number of garbage collections.

Java heap memory is divided into Young area and Old area according to generational age. Object allocation will first go to Young area and reach a certain generational age (-XX:MaxTenuringThreshold can be set in size, the default is 15) and it will enter Old area (Note: If an object is too large, it will directly enter the Old area).

The reason for this division is that if the entire heap has only one area, then all objects in the heap need to be scanned every time during garbage collection, which is a waste of performance. In fact, the life cycle of most Java objects is very short. Once an object cannot be recycled many times, it can be considered that it may not be recycled during the next garbage collection, so the garbage collection in Young and Old areas can be Separately, only when the Young area still does not make room after garbage collection, then it will trigger the garbage collection of the Old area.

Insert picture description here

The Young area
is now divided into the Young area. Let's look at the following scene. The Young area below is a general picture after garbage collection:

Insert picture description here

If you say that an object comes now and it takes up the size of two objects, you will find that you can't put it down. At this time, GC (garbage collection) will be triggered, but once the GC (garbage collection) is triggered, it will affect the user thread. Yes, because in the GC process, in order to ensure that the object reference does not change constantly, all user threads need to be stopped. Sun calls this event: Stop the World (STW). These will be introduced in detail in the next article on garbage collection, so I won't go into depth here.

So in general, the less GC, the better. In fact, you can see that at least 3 objects can be placed in the above figure. As long as the objects are placed in order, they can be placed, so this is the result. The problem is, there is clearly space, but because the space is not continuous, the object fails to apply for memory, which causes the GC to be triggered, so how to solve this problem?

The solution is to put the objects in the Young area in order, so a method was developed to divide the Young area again into two areas: Eden area and Survivor area.

Insert picture description here

The specific operation is: After an object comes, it is allocated to the Eden area. After the Eden area is full, the GC is triggered. After the GC, in order to prevent space discontinuity, copy the surviving object to the Survivor area, and then the Eden area can be used. Completely cleaned up, of course, there is a prerequisite for doing so, that is, most objects have a very short life cycle, and most of the objects in the Eden area can be recycled by a basic garbage collection (this premise is summarized through testing) .

When the GC is triggered, the Survivor area will also be recycled. It does not mean that only the Eden area is triggered alone, but this problem comes again. The Eden area guarantees that the space is basically continuous, but the Survivor area may generate space fragments, resulting in discontinuity. So we divided the Survivor area into two again:

Insert picture description here

At this time, the work flow becomes like this again: first, allocate space in the Eden area. After the Eden area is full, the GC is triggered. After the GC, the surviving objects are copied to the S0 area (the S1 area is empty), and then the objects are allocated in the Eden area. , After triggering the GC again, if it is found that the S0 area cannot fit (space fragmentation, there is actually space), then copy the S0 area object to the S1 area, and copy the surviving object to the S1 area. At this time, the S0 area is empty Yes, and repeat the operation in turn. If the space object in the S0 or S1 area cannot be put down after copying and moving, it means that it is really full at this time, then go to the elderly area to borrow some space (this is the guarantee mechanism , The old age needs to provide this kind of space allocation guarantee), if the old area is not enough, it will trigger the Full GC, if it is still not enough, it will throw an OutOfMemeoyError exception.

Note: In order to ensure the smooth progress of each copy between the two areas S0 and S1, the size of the two areas S0 and S1 must be the same, and one area must be empty at the same time. Although this approach will result in a small amount of waste of space, it is worthwhile to integrate other performance improvements.

Old area
When the object in the Young area reaches the set generational age, the object will enter the Old area. When the Old area is full, Full GC will be triggered. If the space still cannot be cleaned up, an OutOfMemeoyError will be thrown.

Noun literacy

Many new nouns have been mentioned above, but in fact many of these nouns have other names. I still think it is necessary to understand this.

Garbage collection: referred to as GC.

Minor GC: GC for the new generation

Major GC: For the GC of the old age, generally the old age triggers the GC while also triggering the Minor GC, which is equivalent to triggering the Full GC.

Full GC: GC occurs simultaneously in the new generation + the old generation.

Young District: New Generation

Old district: the old age

Eden District: No Chinese translation (Eden Garden?)

Surcivor District: Survival District

S0 and S1: also called from area and to area. Note that the two areas from from and to are constantly changing their identities, and S0 and S1 must be equal, and an area is guaranteed to be empty

An object's life trajectory diagram

From the above introduction, everyone should have a general impression that an object will continue to circulate in the Eden area, S0 area, S1 area, and Old area (of course, except for short-lived objects that will be recycled at the beginning), we can get the following one flow chart:
Insert picture description here

This article mainly introduces how a Java object is stored in the heap, and combines the memory layout of the Java object to demonstrate the size of a common object. Then it also analyzes the space division in the heap and the reason for the division. This article involves GC related The knowledge has not been explained in depth, and related knowledge about GC and GC algorithms and GC collectors will be analyzed in detail in the next article.

So far, this article about interviewers: new Object() in Java occupies a few bytes is introduced here. For more related Java new Object() bytes, please follow the editor or add QQ1411943564. Hope you will support more in the future. Editor!

Guess you like

Origin blog.csdn.net/dcj19980805/article/details/115242323