How does the JVM get the length of the array

How does the JVM get the length of the array

This note mainly records the arrays we write in java, such as int arr[] ={1,2,3};, then we use int len ​​= arr.length; how the underlying jvm gets the length of the
array ; the array is in The bottom layer of jvm is dynamically generated, which means that it is not static. It is similar to the hashcode of an object. If you have not overridden the hashcode method, the hashcode of the object is the memory address of the object by default, so the hashcode is also generated dynamically , Our array is the same. After we define the array, the array can be dynamically generated, added and deleted dynamically at runtime, so the length of the array is also dynamically generated; here we use the program and HSDB to prove the array How to get the length at the bottom of the jvm, first look at the following program:

public class T0819 {
    
    


    public static void main(String[] args) {
    
    
        int arr [] ={
    
    1,2,3};
        int length = arr.length;
        System.out.println(length);
    }
}

Let’s check the bytecode information through javap -verbose T0819.class

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=3, args_size=1
         0: iconst_3
         1: newarray       int
         3: dup
         4: iconst_0
         5: iconst_1
         6: iastore
         7: dup
         8: iconst_1
         9: iconst_2
        10: iastore
        11: dup
        12: iconst_2
        13: iconst_3
        14: iastore
        15: astore_1
        16: aload_1
        17: arraylength
        18: istore_2
        19: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        22: iload_2
        23: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        26: return
      LineNumberTable:
        line 7: 0
        line 8: 16
        line 9: 19
        line 10: 26
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      27     0  args   [Ljava/lang/String;
           16      11     1   arr   [I
           19       8     2 length   I
}

Look at the program counter 17, arraylength. To put it bluntly, to figure out how the array length is dynamically obtained in the jvm depends on how the jvm processes the bytecode instruction arraylength; here I found a code block of how openjdk obtains the array length :

CASE(_arraylength):
{
    
    
  arrayOop ary = (arrayOop) STACK_OBJECT(-1);
  CHECK_NULL(ary);
  SET_STACK_INT(ary->length(), -1);
  UPDATE_PC_AND_CONTINUE(1);
}


int length() const {
    
    
    return *(int*)(((intptr_t)this) + length_offset_in_bytes());
 }

The CASE code is to get the length of our array. The third line of code in the case is to get the length and push it onto the stack.
We mainly analyze the length() method, which uses the this pointer to get the first position of the array, and then add The offset of the array is added to get the length of our array, we look at the following figure:
Insert picture description here
((intptr_t)this)=get the first position of our array
length_offset_in_bytes()=get the offset of our array in memory
and then add , Take the address and get the length of our array

Let's look at the function length_offset_in_bytes() to get the offset

//如果不压缩,则在arrayOopDesc中声明的非静态字段之后分配
//如果压缩,它将占用oopDesc中_klass字段的后半部分
static int length_offset_in_bytes() {
    
    
    return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
                               sizeof(arrayOopDesc);
  }

Look at the above code, there is a parameter UseCompressedClassPointers, this parameter is also part of our jvm tuning, what does this parameter mean? We know from the above notes that our object memory layout has an object header, instance data and alignment padding;
and the object header is divided into mark word, type pointer and array length, and type pointer compression and uncompressed bytes are not The same,
then what is the difference between UseCompressedClassPointers and UseCompressedoops?
UseCompressedoops compresses the length of the object pointer, while UseCompressedClassPointers compresses the length of the Klass object pointer. If we enable UseCompressedoops, then UseCompressedClassPointers is turned on by default, which
means that UseCompressedoops includes UseCompressedClassPointers.
First, let’s analyze the array: The
corresponding Klass is: TypeArrayKlass instance The
corresponding oop is: TypeArrayOop instance

And the code block of the type pointer in jvm is:

union _metadata {
    
    
    Klass*      _klass;         8B
    narrowKlass _compressed_klass;    4B
  } _metadata;

It is a consortium, the whole consortium occupies 8B of space, if we are compressed, then 4B will be used, if we do not compress, then 8B will be used, then if we compress, is it a waste of space? The comment of the length_offset_in_bytes() method has been written, we will begin to analyze the whole problem below.
Object memory layout
Object header
Mark Word
Klass pointer
Array length
Instance data
Fill

If we enable pointer compression:
Mark Word 8B
Klass pointer 4B
array length 4B
then pointer length + array length = 4B + 4B = 8B
if we do not compress it is = 8B + 4B = 12B

So we understand the sentence in the code comment "If compressed, it will occupy the second half of the _klass field in oopDesc."
If compressed, the type pointer is 4B, because our

union _metadata {
    
    
    Klass*      _klass;         8B
    narrowKlass _compressed_klass;    4B
  } _metadata;

It is 8B. Compressed and used is _compressed_klass in the union, and our array length is 4B, so we use 4B in the second half of _klass, which means that, that is to say, our array length is The second half of the union, if pointer compression is turned on.

We come through our array length HSDB to see the next:
Insert picture description here
we are opened pointer compression, it is --metadata._compressed_klass, let's see the next memory view it:
Insert picture description here
we closed pointer compression: -XX: -UseCompressedClassPointers
Insert picture description here
a fancy The picture is to know that pointer compression is turned off
Insert picture description here

Guess you like

Origin blog.csdn.net/scjava/article/details/108219216