Skip to content

java 对象大小

Posted on:January 11, 2023 at 08:43 AM

背景

排查一个gc问题的时候想到需要了解java的对象大小

举例这样创建一个1099 的对象会占用多少个字节呢?

那如果是一个特定的对象NumClass

public class NumClass{
    public int num1 ;
    public int num2 ; 
}

那样创建NunClass[] 又占用多少字节呢?

## 这样 的array占用多少字节呢? 
Object[] array = new Object[10245] ; 
## 这样 的array占用多少字节呢? 
Object[] array = new NumClass[10245] ; 

结论是两者占用的字节是一样的

object 数组例子

先上最简单的new Object的代码,在这个例子里面: 创建了一个长度是10245的对象数组

package com;
public class Hello{
        public static volatile Object[] arr ;
        public static void main(String [] argv){
                arr = new Object[10245];    // 创建一个对象数组 , 数组也是一个对象 , 那么这个对象有多大呢? 
                arr[1] = "hihi";

        }
}

实际上是在64位机器上,没有开启指针压缩的情况下是: 8+ 4 + 10245*8个字节长度

oop 是指针oopDesc* 的别名

typedef class oopDesc*                    oop;
typedef class   instanceOopDesc*            instanceOop;
typedef class   arrayOopDesc*               arrayOop;
typedef class     objArrayOopDesc*            objArrayOop;
typedef class     typeArrayOopDesc*           typeArrayOop;
+-----------++----------++-------++------+           
|           ||          ||       ||      |           
|           ||          ||       ||      |           
|  MarkWord || length   ||  oop  ||  oop |                  
+-----------++----------++-------++------+ repeat 10254 次  

jol

核心函数:

jol\jol-core\src\main\java\org\openjdk\jol\layouters\CurrentLayouter.java

    @Override
    public ClassLayout layout(ClassData data) {
        VirtualMachine vm = VM.current();

        if (data.isArray()) {
            // special case of arrays
            int base = vm.arrayBaseOffset(data.arrayComponentType());
            int scale = vm.arrayIndexScale(data.arrayComponentType());

            long instanceSize = MathUtil.align(base + data.arrayLength() * scale, vm.objectAlignment());

            SortedSet<FieldLayout> result = new TreeSet<>();
            result.add(new FieldLayout(FieldData.create(data.arrayClass(), "<elements>", data.arrayComponentType()), base, scale * data.arrayLength()));
            return ClassLayout.create(data, result, CURRENT, instanceSize, false);
        }

        Collection<FieldData> fields = data.fields();

        SortedSet<FieldLayout> result = new TreeSet<>();
        for (FieldData f : fields) {
            result.add(new FieldLayout(f, vm.fieldOffset(f.refField()), vm.sizeOfField(f.typeClass())));
        }

        long instanceSize;
        if (result.isEmpty()) {
            instanceSize = vm.objectHeaderSize();
        } else {
            FieldLayout f = result.last();
            instanceSize = f.offset() + f.size();
            // TODO: This calculation is incorrect if there is a trailing @Contended field, or the instance is @Contended
        }
        instanceSize = MathUtil.align(instanceSize, vm.objectAlignment());
        return ClassLayout.create(data, result, CURRENT, instanceSize, true);
    }
  static int length_offset_in_bytes() {
    return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
                               sizeof(arrayOopDesc);
  }

创建一个数组

(gdb) bt
#0  arrayOopDesc::length_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:83
#1  0x00007f93c2fdc06e in arrayOopDesc::length_addr_impl (obj_ptr=0x7162010c0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:67
#2  0x00007f93c2fdc0ba in arrayOopDesc::length (this=0x7162010c0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:114
#3  0x00007f93c3239521 in arrayOopDesc::is_within_bounds (this=0x7162010c0, index=10) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:110
#4  0x00007f93c3239690 in typeArrayOopDesc::byte_at_addr (this=0x7162010c0, which=10) at /var/jdk/src/hotspot/share/oops/typeArrayOop.inline.hpp:48
#5  0x00007f93c323972d in typeArrayOopDesc::byte_at_put (this=0x7162010c0, which=10, contents=112 'p') at /var/jdk/src/hotspot/share/oops/typeArrayOop.inline.hpp:96
#6  0x00007f93c389e259 in java_lang_String::create_from_unicode (unicode=0x7f93bc037c88, length=33, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:300
#7  0x00007f93c3f7b91d in StringTable::do_intern (string_or_null_h=..., name=0x7f93bc037c88, len=33, hash=2694772907, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/stringTable.cpp:347
#8  0x00007f93c3f7b87e in StringTable::intern (string_or_null_h=..., name=0x7f93bc037c88, len=33, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/stringTable.cpp:336
#9  0x00007f93c3f7b5b0 in StringTable::intern (symbol=0x7f93c0018d38, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/stringTable.cpp:296
#10 0x00007f93c35740b5 in ConstantPool::uncached_string_at (this=0x7f938c02e0a0, which=250, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/oops/constantPool.cpp:1171
#11 0x00007f93c36a19cd in fieldDescriptor::string_initial_value (this=0x7f93c2bd3a68, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/runtime/fieldDescriptor.cpp:103
#12 0x00007f93c389ff2d in initialize_static_string_field (fd=0x7f93c2bd3a68, mirror=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:809
#13 0x00007f93c38a0444 in initialize_static_field (fd=0x7f93c2bd3a68, mirror=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:866
#14 0x00007f93c3869f51 in InstanceKlass::do_local_static_fields (this=0x8000431a0, f=0x7f93c38a0365 <initialize_static_field(fieldDescriptor*, Handle, JavaThread*)>, mirror=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/oops/instanceKlass.cpp:1672
#15 0x00007f93c38a08d5 in java_lang_Class::initialize_mirror_fields (k=0x8000431a0, mirror=..., protection_domain=..., classData=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:930
#16 0x00007f93c38a10d1 in java_lang_Class::create_mirror (k=0x8000431a0, class_loader=..., module=..., protection_domain=..., classData=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:1035
#17 0x00007f93c34c6144 in ClassFileParser::fill_instance_klass (this=0x7f93c2bd3dd0, ik=0x8000431a0, changed_by_loadhook=false, cl_inst_info=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/classFileParser.cpp:5426
#18 0x00007f93c34c532e in ClassFileParser::create_instance_klass (this=0x7f93c2bd3dd0, changed_by_loadhook=false, cl_inst_info=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/classFileParser.cpp:5255
#19 0x00007f93c3b554d1 in KlassFactory::create_from_stream (stream=0x7f93bc036fb0, name=0x7f93c00001f8, loader_data=0x7f93bc121170, cl_info=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/klassFactory.cpp:202
#20 0x00007f93c34d86e9 in ClassLoader::load_class (name=0x7f93c00001f8, search_append_only=false, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/classLoader.cpp:1231
#21 0x00007f93c4000806 in SystemDictionary::load_instance_class_impl (class_name=0x7f93c00001f8, class_loader=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:1289
#22 0x00007f93c4000ba3 in SystemDictionary::load_instance_class (name_hash=2036240099, name=0x7f93c00001f8, class_loader=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:1354
#23 0x00007f93c3ffeca9 in SystemDictionary::resolve_instance_class_or_null (name=0x7f93c00001f8, class_loader=..., protection_domain=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:723
#24 0x00007f93c3ffd82e in SystemDictionary::resolve_instance_class_or_null_helper (class_name=0x7f93c00001f8, class_loader=..., protection_domain=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:294
#25 0x00007f93c3ffd6d4 in SystemDictionary::resolve_or_null (class_name=0x7f93c00001f8, class_loader=..., protection_domain=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:277
#26 0x00007f93c3ffd617 in SystemDictionary::resolve_or_fail (class_name=0x7f93c00001f8, class_loader=..., protection_domain=..., throw_error=true, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:263
#27 0x00007f93c32b8d98 in SystemDictionary::resolve_or_fail (class_name=0x7f93c00001f8, throw_error=true, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.hpp:100
#28 0x00007f93c40dca98 in vmClasses::resolve (id=vmClassID::Throwable_klass_knum, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.cpp:99
#29 0x00007f93c40dcb96 in vmClasses::resolve_until (limit_id=vmClassID::SoftReference_klass_knum, start_id=@0x7f93c2bd48f0: vmClassID::Cloneable_klass_knum, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.cpp:108
#30 0x00007f93c40dd59a in vmClasses::resolve_through (last_id=vmClassID::Reference_klass_knum, start_id=@0x7f93c2bd48f0: vmClassID::Cloneable_klass_knum, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.hpp:64
#31 0x00007f93c40dce23 in vmClasses::resolve_all (__the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.cpp:168
#32 0x00007f93c4001ab2 in SystemDictionary::initialize (__the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:1655
#33 0x00007f93c40812fb in Universe::genesis (__the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/memory/universe.cpp:335
#34 0x00007f93c408378f in universe2_init () at /var/jdk/src/hotspot/share/memory/universe.cpp:937
#35 0x00007f93c3863d8a in init_globals () at /var/jdk/src/hotspot/share/runtime/init.cpp:132
#36 0x00007f93c404a1ca in Threads::create_vm (args=0x7f93c2bd4d50, canTryAgain=0x7f93c2bd4c5b) at /var/jdk/src/hotspot/share/runtime/thread.cpp:2843
#37 0x00007f93c396f43b in JNI_CreateJavaVM_inner (vm=0x7f93c2bd4da8, penv=0x7f93c2bd4db0, args=0x7f93c2bd4d50) at /var/jdk/src/hotspot/share/prims/jni.cpp:3613
#38 0x00007f93c396f787 in JNI_CreateJavaVM (vm=0x7f93c2bd4da8, penv=0x7f93c2bd4db0, args=0x7f93c2bd4d50) at /var/jdk/src/hotspot/share/prims/jni.cpp:3701
#39 0x00007f93c50e6a6a in InitializeJVM (pvm=0x7f93c2bd4da8, penv=0x7f93c2bd4db0, ifn=0x7f93c2bd4e00) at /var/jdk/src/java.base/share/native/libjli/java.c:1459
#40 0x00007f93c50e35ec in JavaMain (_args=0x7ffedd44e1a0) at /var/jdk/src/java.base/share/native/libjli/java.c:411
#41 0x00007f93c50ea5ec in ThreadJavaMain (args=0x7ffedd44e1a0) at /var/jdk/src/java.base/unix/native/libjli/java_md.c:651
#42 0x00007f93c4f45b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#43 0x00007f93c4fd6bb4 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100

分配数组大小:

  static int array_size(int length) {
    const uint OopsPerHeapWord = HeapWordSize/heapOopSize;
    assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0),
           "Else the following (new) computation would be in error");
    uint res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord;
#ifdef ASSERT
    // The old code is left in for sanity-checking; it'll
    // go away pretty soon. XXX
    // Without UseCompressedOops, this is simply:
    // oop->length() * HeapWordsPerOop;
    // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer.
    // The oop elements are aligned up to wordSize
    const uint HeapWordsPerOop = heapOopSize/HeapWordSize;
    uint old_res;
    if (HeapWordsPerOop > 0) {
      old_res = length * HeapWordsPerOop;
    } else {
      old_res = align_up((uint)length, OopsPerHeapWord)/OopsPerHeapWord;
    }
    assert(res == old_res, "Inconsistency between old and new.");
#endif  // ASSERT
    return res;
  }
Thread 2 "java" hit Breakpoint 5, jni_invoke_static (env=0x7fca48029310, result=0x7fca4c534bf0, receiver=0x0, call_type=JNI_STATIC, method_id=0x7fca48542d50, args=0x7fca4c534c60, __the_thread__=0x7fca48029030) at /var/jdk/src/hotspot/share/prims/jni.cpp:881
881       args->push_arguments_on(&java_args);
(gdb) p method._value->print()
{method}
 - this oop:          0x00007fca14411240
 - method holder:     'com/Hello'
 - constants:         0x00007fca14411020 constant pool [20] {0x00007fca14411020} for 'com/Hello' cache=0x00007fca14411348
 - access:            0x9  public static 
 - name:              'main'
 - signature:         '([Ljava/lang/String;)V'
 - max stack:         2
 - max locals:        1
 - size of params:    1
 - method size:       13
 - vtable index:      -2
 - i2i entry:         0x00007fca3900dc00
 - adapters:          AHE@0x00007fca4812b8d0: 0xb i2c: 0x00007fca39114d60 c2i: 0x00007fca39114e1a c2iUV: 0x00007fca39114de4 c2iNCI: 0x00007fca39114e57
 - compiled entry     0x00007fca39114e1a
 - code size:         10
 - code start:        0x00007fca14411230
 - code end (excl):   0x00007fca1441123a
 - checked ex length: 0
 - linenumber start:  0x00007fca1441123a
 - localvar length:   0
$17 = void
(gdb) bt
#0  jni_invoke_static (env=0x7fca48029310, result=0x7fca4c534bf0, receiver=0x0, call_type=JNI_STATIC, method_id=0x7fca48542d50, args=0x7fca4c534c60, __the_thread__=0x7fca48029030) at /var/jdk/src/hotspot/share/prims/jni.cpp:881
#1  0x00007fca4d2c141c in jni_CallStaticVoidMethod (env=0x7fca48029310, cls=0x7fca4802b368, methodID=0x7fca48542d50) at /var/jdk/src/hotspot/share/prims/jni.cpp:1710
#2  0x00007fca4ea4415e in JavaMain (_args=0x7fff1ad56b60) at /var/jdk/src/java.base/share/native/libjli/java.c:545
#3  0x00007fca4ea4a5ec in ThreadJavaMain (args=0x7fff1ad56b60) at /var/jdk/src/java.base/unix/native/libjli/java_md.c:651
#4  0x00007fca4e8a5b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#5  0x00007fca4e936bb4 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100
Thread 2 "java" hit Breakpoint 5, jni_invoke_static (env=0x7f8674029310, result=0x7f86791b0bf0, receiver=0x0, call_type=JNI_STATIC, method_id=0x7f8674652560, args=0x7f86791b0c60, __the_thread__=0x7f8674029030) at /var/jdk/src/hotspot/share/prims/jni.cpp:881
881       args->push_arguments_on(&java_args);
(gdb) p method._value->print()
{method}
 - this oop:          0x00007f8644411240
 - method holder:     'com/Hello'
 - constants:         0x00007f8644411020 constant pool [20] {0x00007f8644411020} for 'com/Hello' cache=0x00007f8644411348
 - access:            0x9  public static 
 - name:              'main'
 - signature:         '([Ljava/lang/String;)V'
 - max stack:         2
 - max locals:        1
 - size of params:    1
 - method size:       13
 - vtable index:      -2
 - i2i entry:         0x00007f866500dc00
 - adapters:          AHE@0x00007f867412b8d0: 0xb i2c: 0x00007f8665114d60 c2i: 0x00007f8665114e1a c2iUV: 0x00007f8665114de4 c2iNCI: 0x00007f8665114e57
 - compiled entry     0x00007f8665114e1a
 - code size:         10
 - code start:        0x00007f8644411230
 - code end (excl):   0x00007f864441123a
 - checked ex length: 0
 - linenumber start:  0x00007f864441123a
 - localvar length:   0
$23 = void
(gdb) enable 1
(gdb) c
Continuing.

Thread 2 "java" hit Breakpoint 1, oopFactory::new_objArray (klass=0x800040f80, length=2019, __the_thread__=0x7f8674029030) at /var/jdk/src/hotspot/share/memory/oopFactory.cpp:118
118       assert(klass->is_klass(), "must be instance class");
(gdb) bt
#0  oopFactory::new_objArray (klass=0x800040f80, length=2019, __the_thread__=0x7f8674029030) at /var/jdk/src/hotspot/share/memory/oopFactory.cpp:118
#1  0x00007f8679e68a5b in InterpreterRuntime::anewarray (current=0x7f8674029030, pool=0x7f8644411020, index=2, size=2019) at /var/jdk/src/hotspot/share/interpreter/interpreterRuntime.cpp:254
#2  0x00007f8665024083 in ?? ()
#3  0x00007f867b4520a0 in TemplateInterpreter::_active_table () from /var/jdk/build/linux-x86_64-server-slowdebug/jdk/lib/server/libjvm.so
#4  0x00007f8665024002 in ?? ()
#5  0x00007f86791b07b0 in ?? ()
#6  0x00007f8644411233 in ?? ()
#7  0x00007f86791b0808 in ?? ()
#8  0x00007f8644411348 in ?? ()
#9  0x0000000000000000 in ?? ()
Bottom (innermost) frame selected; you cannot go down.
(gdb) p _do_zero 
$35 = true
(gdb) n
413       if (_do_zero) {
(gdb) n
414         mem_clear(mem);
(gdb) n
416       arrayOopDesc::set_length(mem, _length);
(gdb) l
411       // concurrent GC.
412       assert(_length >= 0, "length should be non-negative");
413       if (_do_zero) {
414         mem_clear(mem);
415       }
416       arrayOopDesc::set_length(mem, _length);
417       return finish(mem);
418     }
419
420     oop ClassAllocator::initialize(HeapWord* mem) const {
(gdb) up
#1  0x00007f867a27af4b in MemAllocator::allocate (this=0x7f86791b0650) at /var/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:365
365           obj = initialize(mem);
(gdb) down
#0  ObjArrayAllocator::initialize (this=0x7f86791b0650, mem=0x715e73dd0) at /var/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:416
416       arrayOopDesc::set_length(mem, _length);
(gdb) s
arrayOopDesc::set_length (mem=0x715e73dd0, length=2019) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:122
122         *length_addr_impl(mem) = length;
(gdb) s
arrayOopDesc::length_addr_impl (obj_ptr=0x715e73dd0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:66
66          char* ptr = static_cast<char*>(obj_ptr);
(gdb) l
61          return (int)hs;
62        }
63
64        // Returns the address of the length "field".  See length_offset_in_bytes().
65        static int* length_addr_impl(void* obj_ptr) {
66          char* ptr = static_cast<char*>(obj_ptr);
67          return reinterpret_cast<int*>(ptr + length_offset_in_bytes());
68        }
69
70        // Check whether an element of a typeArrayOop with the given type must be
(gdb) n
67          return reinterpret_cast<int*>(ptr + length_offset_in_bytes());
(gdb) s
arrayOopDesc::length_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:83
83                                     sizeof(arrayOopDesc);
(gdb) l
78        // The _length field is not declared in C++.  It is allocated after the
79        // declared nonstatic fields in arrayOopDesc if not compressed, otherwise
80        // it occupies the second half of the _klass field in oopDesc.
81        static int length_offset_in_bytes() {
82          return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
83                                     sizeof(arrayOopDesc);
84        }
85
86        // Returns the offset of the first element.
87        static int base_offset_in_bytes(BasicType type) {
(gdb) p Use
Display all 161 possibilities? (y or n)
(gdb) p UseCompressedClassPointers   
$36 = true
(gdb) s
82          return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
(gdb) s
oopDesc::klass_gap_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/oop.hpp:307
307         assert(has_klass_gap(), "only applicable to compressed klass pointers");
(gdb) l
302
303       // for code generation
304       static int mark_offset_in_bytes()      { return offset_of(oopDesc, _mark); }
305       static int klass_offset_in_bytes()     { return offset_of(oopDesc, _metadata._klass); }
306       static int klass_gap_offset_in_bytes() {
307         assert(has_klass_gap(), "only applicable to compressed klass pointers");
308         return klass_offset_in_bytes() + sizeof(narrowKlass);
309       }
310
311       // for error reporting
(gdb) n
oopDesc::klass_gap_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/oop.hpp:308
308         return klass_offset_in_bytes() + sizeof(narrowKlass);
(gdb) n
309       }
(gdb) n
arrayOopDesc::length_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:83
83                                     sizeof(arrayOopDesc);
(gdb) n
84        }
(gdb) n
arrayOopDesc::length_addr_impl (obj_ptr=0x715e73dd0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:68
68        }
(gdb) n
arrayOopDesc::set_length (mem=0x715e73dd0, length=2019) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:122
122         *length_addr_impl(mem) = length;
(gdb) n              
123       }
(gdb) p  (int *)mem@20
Only values in memory can be extended with '@'.
(gdb) p  *(int *)mem@20
$37 = {-1163019586, -1163019586, -1163019586, 2019, 0 <repeats 16 times>}

byte code 生成入口

// jdk/src/hotspot/share/interpreter/templateInterpreter.cpp
void DispatchTable::set_entry(int i, EntryPoint& entry) {
  assert(0 <= i && i < length, "index out of bounds");
  assert(number_of_states == 10, "check the code below");
  _table[btos][i] = entry.entry(btos);
  _table[ztos][i] = entry.entry(ztos);
  _table[ctos][i] = entry.entry(ctos);
  _table[stos][i] = entry.entry(stos);
  _table[atos][i] = entry.entry(atos);
  _table[itos][i] = entry.entry(itos);
  _table[ltos][i] = entry.entry(ltos);
  _table[ftos][i] = entry.entry(ftos);
  _table[dtos][i] = entry.entry(dtos);
  _table[vtos][i] = entry.entry(vtos);
}
//src/hotspot/share/interpreter/bytecodes.hpp
   _new                  = 187, // 0xbb
    _newarray             = 188, // 0xbc
    _anewarray            = 189, // 0xbd
    _arraylength          = 190, // 0xbe

堆栈:

Thread 2 "java" hit Breakpoint 13, 0x00007fffe1011b13 in ?? ()
(gdb) x/20i $pc
=> 0x7fffe1011b13:	movzwl 0x1(%r13),%eax
   0x7fffe1011b18:	bswap  %eax
   0x7fffe1011b1a:	sar    $0x10,%eax
   0x7fffe1011b1d:	movzbl 0x3(%r13),%ebx
   0x7fffe1011b22:	add    $0x3,%r13
   0x7fffe1011b26:	movabs $0x7ffff7bca0a0,%r10
   0x7fffe1011b30:	jmp    *(%r10,%rbx,8)
   0x7fffe1011b34:	nop
   0x7fffe1011b35:	nop
   0x7fffe1011b36:	nop
   0x7fffe1011b37:	nop
   0x7fffe1011b38:	int3   
   0x7fffe1011b39:	int3   
   0x7fffe1011b3a:	int3   
   0x7fffe1011b3b:	int3   
   0x7fffe1011b3c:	int3   
   0x7fffe1011b3d:	int3   
   0x7fffe1011b3e:	int3   
   0x7fffe1011b3f:	int3   
   0x7fffe1011b40:	and    %al,(%rax,%rax,1)
0x00007fffe1011b1d in ?? ()
(gdb) info registers 
rax            0x2805              10245
rbx            0x11                17
rcx            0x2                 2
rdx            0x8                 8
rsi            0x555555581230      93824992416304
rdi            0x7ffff0028f70      140737220087664
rbp            0x7ffff59fe7f8      0x7ffff59fe7f8
rsp            0x7ffff59fe7b0      0x7ffff59fe7b0
r8             0x8                 8
r9             0x0                 0
r10            0x7ffff7bcc8a0      140737349732512
r11            0x216               534
r12            0x0                 0
r13            0x7fffb4411230      140736217551408
r14            0x7ffff59fe808      140737314285576
r15            0x7ffff0028f70      140737220087664
rip            0x7fffe1011b1d      0x7fffe1011b1d
eflags         0x216               [ PF AF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

anewarray 汇编代码:

(gdb) x/20i $pc
=> 0x7fffe102400a:	lea    0x8(%rsp),%rax
   0x7fffe102400f:	mov    %r13,-0x40(%rbp)
   0x7fffe1024013:	cmpq   $0x0,-0x10(%rbp)
   0x7fffe102401b:	je     0x7fffe1024035
   0x7fffe1024021:	movabs $0x7ffff71becc8,%rdi
   0x7fffe102402b:	and    $0xfffffffffffffff0,%rsp
   0x7fffe102402f:	call   0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
   0x7fffe1024034:	hlt    
   0x7fffe1024035:	push   %r10
   0x7fffe1024037:	cmp    0x16ae2ec2(%rip),%r12        # 0x7ffff7b06f00 <_ZN14CompressedOops11_narrow_oopE>
   0x7fffe102403e:	je     0x7fffe1024058
   0x7fffe1024044:	movabs $0x7ffff7311c28,%rdi
   0x7fffe102404e:	and    $0xfffffffffffffff0,%rsp
   0x7fffe1024052:	call   0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
   0x7fffe1024057:	hlt    
   0x7fffe1024058:	pop    %r10
   0x7fffe102405a:	mov    %r15,%rdi
   0x7fffe102405d:	vzeroupper 
   0x7fffe1024060:	mov    %rbp,0x2d0(%r15)
   0x7fffe1024067:	mov    %rax,0x2c0(%r15)
(gdb) x/200i $pc
=> 0x7fffe102400a:	lea    0x8(%rsp),%rax
   0x7fffe102400f:	mov    %r13,-0x40(%rbp)
   0x7fffe1024013:	cmpq   $0x0,-0x10(%rbp)
   0x7fffe102401b:	je     0x7fffe1024035
   0x7fffe1024021:	movabs $0x7ffff71becc8,%rdi
   0x7fffe102402b:	and    $0xfffffffffffffff0,%rsp
   0x7fffe102402f:	call   0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
   0x7fffe1024034:	hlt    
   0x7fffe1024035:	push   %r10
   0x7fffe1024037:	cmp    0x16ae2ec2(%rip),%r12        # 0x7ffff7b06f00 <_ZN14CompressedOops11_narrow_oopE>
   0x7fffe102403e:	je     0x7fffe1024058
   0x7fffe1024044:	movabs $0x7ffff7311c28,%rdi
   0x7fffe102404e:	and    $0xfffffffffffffff0,%rsp
   0x7fffe1024052:	call   0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
   0x7fffe1024057:	hlt    
   0x7fffe1024058:	pop    %r10
   0x7fffe102405a:	mov    %r15,%rdi
   0x7fffe102405d:	vzeroupper 
   0x7fffe1024060:	mov    %rbp,0x2d0(%r15)
   0x7fffe1024067:	mov    %rax,0x2c0(%r15)
   0x7fffe102406e:	test   $0xf,%esp
   0x7fffe1024074:	je     0x7fffe102408c
   0x7fffe102407a:	sub    $0x8,%rsp
   0x7fffe102407e:	call   0x7ffff65cf968 <_ZN18InterpreterRuntime9anewarrayEP10JavaThreadP12ConstantPoolii>
   0x7fffe1024083:	add    $0x8,%rsp
   0x7fffe1024087:	jmp    0x7fffe1024091
   0x7fffe102408c:	call   0x7ffff65cf968 <_ZN18InterpreterRuntime9anewarrayEP10JavaThreadP12ConstantPoolii>
   0x7fffe1024091:	push   %rax
   0x7fffe1024092:	push   %rdi
   0x7fffe1024093:	push   %rsi
   0x7fffe1024094:	push   %rdx
--Type <RET> for more, q to quit, c to continue without paging--
   0x7fffe1024095:	push   %rcx
   0x7fffe1024096:	push   %r8
   0x7fffe1024098:	push   %r9
   0x7fffe102409a:	push   %r10
   0x7fffe102409c:	push   %r11
   0x7fffe102409e:	test   $0xf,%esp
   0x7fffe10240a4:	je     0x7fffe10240bc
   0x7fffe10240aa:	sub    $0x8,%rsp
   0x7fffe10240ae:	call   0x7ffff5d1c04e <_ZN6Thread7currentEv>
   0x7fffe10240b3:	add    $0x8,%rsp
   0x7fffe10240b7:	jmp    0x7fffe10240c1
   0x7fffe10240bc:	call   0x7ffff5d1c04e <_ZN6Thread7currentEv>
   0x7fffe10240c1:	pop    %r11
   0x7fffe10240c3:	pop    %r10
   0x7fffe10240c5:	pop    %r9
   0x7fffe10240c7:	pop    %r8
   0x7fffe10240c9:	pop    %rcx
   0x7fffe10240ca:	pop    %rdx
   0x7fffe10240cb:	pop    %rsi
   0x7fffe10240cc:	pop    %rdi
   0x7fffe10240cd:	cmp    %rax,%r15
   0x7fffe10240d0:	je     0x7fffe10240ea
   0x7fffe10240d6:	movabs $0x7ffff7311da0,%rdi
   0x7fffe10240e0:	and    $0xfffffffffffffff0,%rsp
   0x7fffe10240e4:	call   0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
   0x7fffe10240e9:	hlt    
   0x7fffe10240ea:	pop    %rax
   0x7fffe10240eb:	movq   $0x0,0x2c0(%r15)
   0x7fffe10240f6:	movq   $0x0,0x2d0(%r15)
   0x7fffe1024101:	movq   $0x0,0x2c8(%r15)
   0x7fffe102410c:	vzeroupper 
--Type <RET> for more, q to quit, c to continue without paging--
   0x7fffe102410f:	cmpq   $0x0,0x8(%r15)
   0x7fffe1024117:	je     0x7fffe1024122
   0x7fffe102411d:	jmp    0x7fffe1000c20
   0x7fffe1024122:	mov    0x318(%r15),%rax
   0x7fffe1024129:	movq   $0x0,0x318(%r15)
   0x7fffe1024134:	mov    -0x40(%rbp),%r13
   0x7fffe1024138:	mov    -0x38(%rbp),%r14
   0x7fffe102413c:	ret    
   0x7fffe102413d:	movzbl 0x3(%r13),%ebx
   0x7fffe1024142:	add    $0x3,%r13
   0x7fffe1024146:	movabs $0x7ffff7bcc0a0,%r10
   0x7fffe1024150:	jmp    *(%r10,%rbx,8)
   0x7fffe1024154:	nop
   0x7fffe1024155:	nop
 

内存分配

用的是jdk11以上版本,我这个jdk是用g1来做gc的,所以看看g1 是怎么分配的

(gdb) bt
#0  HeapRegion::par_allocate_impl (this=0x7ffff00e11b0, min_word_size=256, desired_word_size=63020, actual_size=0x7ffff59fcba8)
    at /home/dai/jdk/src/hotspot/share/gc/g1/heapRegion.inline.hpp:63
#1  0x00007ffff640bdcc in HeapRegion::par_allocate (this=0x7ffff00e11b0, min_word_size=256, desired_word_size=63020, actual_word_size=0x7ffff59fcba8)
    at /home/dai/jdk/src/hotspot/share/gc/g1/heapRegion.inline.hpp:225
#2  0x00007ffff640bfcb in G1AllocRegion::par_allocate (this=0x7ffff0052e10, alloc_region=0x7ffff00e11b0, min_word_size=256, desired_word_size=63020, 
    actual_word_size=0x7ffff59fcba8) at /home/dai/jdk/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp:63
#3  0x00007ffff640c0c6 in G1AllocRegion::attempt_allocation (this=0x7ffff0052e10, min_word_size=256, desired_word_size=63020, actual_word_size=0x7ffff59fcba8)
    at /home/dai/jdk/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp:77
#4  0x00007ffff6447142 in G1Allocator::attempt_allocation (this=0x7ffff0052d50, min_word_size=256, desired_word_size=63020, actual_word_size=0x7ffff59fcba8)
    at /home/dai/jdk/src/hotspot/share/gc/g1/g1Allocator.inline.hpp:62
#5  0x00007ffff6447b1d in G1CollectedHeap::attempt_allocation (this=0x7ffff0048bf0, min_word_size=256, desired_word_size=63020, 
    actual_word_size=0x7ffff59fcba8) at /home/dai/jdk/src/hotspot/share/gc/g1/g1CollectedHeap.cpp:709
#6  0x00007ffff64385ea in G1CollectedHeap::allocate_new_tlab (this=0x7ffff0048bf0, min_size=256, requested_size=63020, actual_size=0x7ffff59fcba8)
    at /home/dai/jdk/src/hotspot/share/gc/g1/g1CollectedHeap.cpp:359
#7  0x00007ffff69e1cf6 in MemAllocator::allocate_inside_tlab_slow (this=0x7ffff59fcc00, allocation=...)
    at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:318
#8  0x00007ffff69e1bc2 in MemAllocator::allocate_inside_tlab (this=0x7ffff59fcc00, allocation=...)
    at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:278
#9  0x00007ffff69e1eb9 in MemAllocator::mem_allocate (this=0x7ffff59fcc00, allocation=...) at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:350
#10 0x00007ffff69e1f22 in MemAllocator::allocate (this=0x7ffff59fcc00) at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:363
#11 0x00007ffff6260d84 in CollectedHeap::array_allocate (this=0x7ffff0048bf0, klass=0x8000407c0, size=106, length=825, do_zero=true, 
    __the_thread__=0x7ffff0028f70) at /home/dai/jdk/src/hotspot/share/gc/shared/collectedHeap.inline.hpp:41
#12 0x00007ffff6db9bf2 in TypeArrayKlass::allocate_common (this=0x8000407c0, length=825, do_zero=true, __the_thread__=0x7ffff0028f70)
    at /home/dai/jdk/src/hotspot/share/oops/typeArrayKlass.cpp:93
#13 0x00007ffff62f7428 in TypeArrayKlass::allocate (this=0x8000407c0, length=825, __the_thread__=0x7ffff0028f70)
    at /home/dai/jdk/src/hotspot/share/oops/typeArrayKlass.hpp:68
#14 0x00007ffff6ab4757 in oopFactory::new_typeArray (type=T_BYTE, length=825, __the_thread__=0x7ffff0028f70)
    at /home/dai/jdk/src/hotspot/share/memory/oopFactory.cpp:93
#15 0x00007ffff65cf8e5 in InterpreterRuntime::newarray (current=0x7ffff0028f70, type=T_BYTE, size=825)
    at /home/dai/jdk/src/hotspot/share/interpreter/interpreterRuntime.cpp:247
#16 0x00007fffe1023eb2 in ?? ()
#17 0x00007ffff7bca0a0 in TemplateInterpreter::_active_table () from /home/dai/jdk/build/linux-x86_64-server-slowdebug/jdk/lib/server/libjvm.so
#18 0x00007fffe1023e31 in ?? ()
#19 0x000000062a47ab38 in ?? ()
#20 0x00007ffff59fcd88 in ?? ()
#21 0x00007fffb43a23e6 in ?? ()
#22 0x00007ffff59fcde8 in ?? ()
#23 0x00007fffb43a3520 in ?? ()
#24 0x0000000000000000 in ?? ()

array_copy 反查

java里面 System.arraycopy 函数就是copy 整个数组到新的数组里面,复制方式是浅拷贝. 最后调用的入口是下面的c++代码.所以可以通过这个函数就可以了解数组的内存布局

void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
                               int dst_pos, int length, TRAPS) {


  ...
    size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(src_pos); <----------------------------- 开始地址
    size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(dst_pos);  <---------------------------- 结束地址
    assert(arrayOopDesc::obj_offset_to_raw<oop>(s, src_offset, NULL) ==
           objArrayOop(s)->obj_at_addr<oop>(src_pos), "sanity");
    assert(arrayOopDesc::obj_offset_to_raw<oop>(d, dst_offset, NULL) ==
           objArrayOop(d)->obj_at_addr<oop>(dst_pos), "sanity");
    do_copy(s, src_offset, d, dst_offset, length, CHECK);
  }
}

所以java的对象数组的内存布局就像下面一样 , 这里的oop 是一个指针

64位下面是8字节

相关阅读