菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
198
0

jvm源码解读--02 Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL); 函数引入的jvm内存分配解析

原创
05/13 14:22
阅读数 36258

current路径:

#0  Array<unsigned char>::operator new (size=8, loader_data=0x7fd4c802e868, length=87, read_only=false, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/utilities/array.hpp:324
#1  0x00007fd4cebf27ba in MetadataFactory::new_writeable_array<unsigned char> (loader_data=0x7fd4c802e868, length=87, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/metadataFactory.hpp:52
#2  0x00007fd4cebf2537 in MetadataFactory::new_writeable_array<unsigned char> (loader_data=0x7fd4c802e868, length=87, value=0 '\000', __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/metadataFactory.hpp:57
#3  0x00007fd4cebe9a95 in ConstantPool::allocate (loader_data=0x7fd4c802e868, length=87, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/oops/constantPool.cpp:47
#4  0x00007fd4ceb28bbc in ClassFileParser::parse_constant_pool (this=0x7fd4d06f2010, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:331
#5  0x00007fd4ceb34e84 in ClassFileParser::parseClassFile (this=0x7fd4d06f2010, name=0x7fd4cc1050e8, loader_data=0x7fd4c802e868, protection_domain=..., host_klass=..., cp_patches=0x0, parsed_name=..., verify=false, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:3774
#6  0x00007fd4ceb439b5 in ClassFileParser::parseClassFile (this=0x7fd4d06f2010, name=0x7fd4cc1050e8, loader_data=0x7fd4c802e868, protection_domain=..., parsed_name=..., verify=false, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.hpp:468
#7  0x00007fd4ceb417cb in ClassLoader::load_classfile (h_name=0x7fd4cc1050e8, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classLoader.cpp:931
#8  0x00007fd4cf181903 in SystemDictionary::load_instance_class (class_name=0x7fd4cc1050e8, class_loader=..., __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1304
#9  0x00007fd4cf17fced in SystemDictionary::resolve_instance_class_or_null (name=0x7fd4cc1050e8, class_loader=..., protection_domain=..., __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:779
#10 0x00007fd4cf17e6be in SystemDictionary::resolve_or_null (class_name=0x7fd4cc1050e8, class_loader=..., protection_domain=..., __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:232
#11 0x00007fd4cf17e12f in SystemDictionary::resolve_or_fail (class_name=0x7fd4cc1050e8, class_loader=..., protection_domain=..., throw_error=true, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:171
#12 0x00007fd4cf17e451 in SystemDictionary::resolve_or_fail (class_name=0x7fd4cc1050e8, throw_error=true, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:212
#13 0x00007fd4cf18327b in SystemDictionary::initialize_wk_klass (id=SystemDictionary::Object_klass_knum, init_opt=0, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1866
#14 0x00007fd4cf18339e in SystemDictionary::initialize_wk_klasses_until (limit_id=SystemDictionary::Cloneable_klass_knum, start_id=@0x7fd4d06f29ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1882
#15 0x00007fd4cf186b86 in SystemDictionary::initialize_wk_klasses_through (end_id=SystemDictionary::Class_klass_knum, start_id=@0x7fd4d06f29ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.hpp:408
#16 0x00007fd4cf1834d0 in SystemDictionary::initialize_preloaded_classes (__the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1901
#17 0x00007fd4cf18319d in SystemDictionary::initialize (__the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1843
#18 0x00007fd4cf1d41d1 in Universe::genesis (__the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:288
#19 0x00007fd4cf1d6439 in universe2_init () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:991
#20 0x00007fd4ced6fa5c in init_globals () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/init.cpp:114
#21 0x00007fd4cf1b7756 in Threads::create_vm (args=0x7fd4d06f2e40, canTryAgain=0x7fd4d06f2dff) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/thread.cpp:3424
#22 0x00007fd4cee22232 in JNI_CreateJavaVM (vm=0x7fd4d06f2e88, penv=0x7fd4d06f2e80, args=0x7fd4d06f2e40) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/prims/jni.cpp:5166
#23 0x00007fd4d00bf780 in InitializeJVM (pvm=0x7fd4d06f2e88, penv=0x7fd4d06f2e80, ifn=0x7fd4d06f2e90) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:1145
#24 0x00007fd4d00bd6f9 in JavaMain (_args=0x7ffdde8bac20) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:371
#25 0x00007fd4d02d9ea5 in start_thread () from /lib64/libpthread.so.0
#26 0x00007fd4cfbe29fd in clone () from /lib64/libc.so.6

进入这个函数

  void* operator new(size_t size, ClassLoaderData* loader_data, int length, bool read_only, TRAPS) throw() {
    size_t word_size = Array::size(length);
    return (void*) Metaspace::allocate(loader_data, word_size, read_only,
                                       MetaspaceObj::array_type(sizeof(T)), CHECK_NULL);
  }

说明length= word_size=12,进入标橘子的函数,解释一下这个T为u1,能看到为case1

static MetaspaceObj::Type array_type(size_t elem_size) { //elem_size=1
    switch (elem_size) {
        case 1: return TypeArrayU1Type; //这个
        case 2: return TypeArrayU2Type;
        case 4: return TypeArrayU4Type;
        case 8: return TypeArrayU8Type;
        default:
            return TypeArrayOtherType;
    }
}    

进入主函数

MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,   //word_size=12
                              bool read_only, MetaspaceObj::Type type, TRAPS) {  //参数type= TypeArrayU1Type
    if (HAS_PENDING_EXCEPTION) {
        assert(false, "Should not allocate with exception pending");
        return NULL;  // caller does a CHECK_NULL too
    }

    assert(loader_data != NULL, "Should never pass around a NULL loader_data. "
                                "ClassLoaderData::the_null_class_loader_data() should have been used.");

    // Allocate in metaspaces without taking out a lock, because it deadlocks
    // with the SymbolTable_lock.  Dumping is single threaded for now.  We'll have
    // to revisit this for application class data sharing.
    if (DumpSharedSpaces) {  //不进入
        assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity");
        Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace();
        MetaWord* result = space->allocate(word_size, NonClassType);
        if (result == NULL) {
            report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
        }

        space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size));

        // Zero initialize.
        Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);

        return result;
    }

    MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType;  //这里mdtype= NonClassType

    // Try to allocate metadata.
    MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype);

    if (result == NULL) {
        // Allocation failed.
        if (is_init_completed()) {
            // Only start a GC if the bootstrapping has completed.

            // Try to clean out some memory and retry.
            result = Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation(
                    loader_data, word_size, mdtype);
        }
    }

    if (result == NULL) {
        report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
    }

    // Zero initialize.
    Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);

    return result;
}

进入主函数,标记为黄色的

Metaspace* ClassLoaderData::metaspace_non_null() {
    assert(!DumpSharedSpaces, "wrong metaspace!");
    // If the metaspace has not been allocated, create a new one.  Might want
    // to create smaller arena for Reflection class loaders also.
    // The reason for the delayed allocation is because some class loaders are
    // simply for delegating with no metadata of their own.
    if (_metaspace == NULL) {                  //不为0 直接返回
        MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
        // Check again if metaspace has been allocated while we were getting this lock.
        if (_metaspace != NULL) {
            return _metaspace;
        }
        if (this == the_null_class_loader_data()) {
            assert (class_loader() == NULL, "Must be");
            set_metaspace(new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType));
        } else if (is_anonymous()) {
            if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
                tty->print_cr("is_anonymous: %s", class_loader()->klass()->internal_name());
            }
            set_metaspace(new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType));
        } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
            if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
                tty->print_cr("is_reflection: %s", class_loader()->klass()->internal_name());
            }
            set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType));
        } else {
            set_metaspace(new Metaspace(_metaspace_lock, Metaspace::StandardMetaspaceType));
        }
    }
    return _metaspace;
}

元空间 _metaspace

上边直接返回没什么可看的,现在看下这个_metaspace

(gdb) p *_metaspace
$2 = (Metaspace) {<CHeapObj<256u>> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7fd4cfa2c870 <vtable for Metaspace+16>}, <No data fields>},
                  static _compressed_class_space_size = 0x40000000, //默认大小40M
                  static _first_chunk_word_size = 0x80000,   //第一个NonClassType类型的MetaChunk的大小
                  static _first_class_chunk_word_size = 0xc000, //第一个ClassType类型的MetaChunk的大小
                  static _commit_alignment = 0x1000, //commit内存的粒度
                  static _reserve_alignment = 0x1000, //reserve内存的粒度
                  _vsm = 0x7fd4c8050298,             //NonClassType类型的元数据对应的SpaceManager
                  _class_vsm = 0x7fd4c8050328,       //ClassType类型的元数据对应的SpaceManager
                  static _space_list = 0x7fd4c802e608, // NonClassType类型的元数据对应的VirtualSpaceList
                  static _class_space_list = 0x7fd4c802e3a8, // ClassType类型的元数据对应的VirtualSpaceList
                  static _chunk_manager_metadata = 0x7fd4c802e778, //NonClassType类型的元数据对应的ChunkManager
                  static _chunk_manager_class = 0x7fd4c802e518,    // ClassType类型的元数据对应的ChunkManager
                  _alloc_record_head = 0x0, //AllocRecord链表的头部元素
                  _alloc_record_tail = 0x0}  //AllocRecord链表的尾部元素

这个现在还不太懂,慢慢来吧

进入主函数标橘子色的后半部分_metaspace->allocate(word_size, mdtype);

MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) {
// DumpSharedSpaces doesn't use class metadata area (yet)
// Also, don't use class_vsm() unless UseCompressedClassPointers is true.
if (is_class_space_allocation(mdtype)) {//不成立
    return  class_vsm()->allocate(word_size); //不进入
    } else {
    return  vsm()->allocate(word_size);
    }
}

SpaceManager* vsm() const { return _vsm; }

_vsm的天下,就是_vsm->allocate()

主流程接着看

MetaWord* SpaceManager::allocate(size_t word_size) {
    MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);

    size_t raw_word_size = get_raw_word_size(word_size);
    BlockFreelist* fl =  block_freelists();
    MetaWord* p = NULL;
    // Allocation from the dictionary is expensive in the sense that
    // the dictionary has to be searched for a size.  Don't allocate
    // from the dictionary until it starts to get fat.  Is this
    // a reasonable policy?  Maybe an skinny dictionary is fast enough
    // for allocations.  Do some profiling.  JJJ
    if (fl->total_size() > allocation_from_dictionary_limit) {
        p = fl->get_block(raw_word_size);
    }
    if (p == NULL) {
        p = allocate_work(raw_word_size);
    }

    return p;
}

进入橘子程序

size_t get_raw_word_size(size_t word_size) {
    size_t byte_size = word_size * BytesPerWord;

    size_t raw_bytes_size = MAX2(byte_size, sizeof(Metablock)); //sizeof(Metablock)=24
    //返回96
    raw_bytes_size = align_size_up(raw_bytes_size, Metachunk::object_alignment());
    size_t raw_word_size = raw_bytes_size / BytesPerWord;
    //返回12
    assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem");

    return raw_word_size;
}

查看类结构

class Metablock : public Metabase<Metablock> {
    friend class VMStructs;
public:
    Metablock(size_t word_size) : Metabase<Metablock>(word_size) {}
};
// Super class of Metablock and Metachunk to allow them to
// be put on the FreeList and in the BinaryTreeDictionary.
template <class T>
class Metabase VALUE_OBJ_CLASS_SPEC {
        size_t _word_size;
        T*     _next;
        T*     _prev;

        protected:
        Metabase(size_t word_size) : _word_size(word_size), _next(NULL), _prev(NULL) {}

        public:
        T* next() const         { return _next; }
        T* prev() const         { return _prev; }
        void set_next(T* v)     { _next = v; assert(v != this, "Boom");}
        void set_prev(T* v)     { _prev = v; assert(v != this, "Boom");}
        void clear_next()       { set_next(NULL); }
        void clear_prev()       { set_prev(NULL); }

        size_t size() const volatile { return _word_size; }
        void set_size(size_t v) { _word_size = v; }

        void link_next(T* ptr)  { set_next(ptr); }
        void link_prev(T* ptr)  { set_prev(ptr); }
        void link_after(T* ptr) {
            link_next(ptr);
            if (ptr != NULL) ptr->link_prev((T*)this);
        }

        uintptr_t* end() const        { return ((uintptr_t*) this) + size(); }

        bool cantCoalesce() const     { return false; }



        bool verify_chunk_in_free_list(T* tc) const { return true; }
        bool verify_par_locked() { return true; }

        void assert_is_mangled() const {/* Don't check "\*/}

        bool is_free()                 { return true; }
};

主流程,进入紫色程序

//进入到这个函数 BlockFreelist* fl =  block_freelists();
BlockFreelist* block_freelists() const {
    return (BlockFreelist*) &_block_freelists;
BlockFreelist _block_freelists;

查看内存内容

(gdb) p _block_freelists
$4 = {_dictionary = 0x0, static WasteMultiplier = 4}

蓝色上边不执行的if判断

if (fl->total_size() > allocation_from_dictionary_limit) {
p = fl->get_block(raw_word_size);
}

size_t total_size() {
    if (dictionary() == NULL) {
        return 0;  //执行到这里
    } else {
        return dictionary()->total_size();
    }
}

 


 

进入蓝色程序,这个就是_vsm

// Returns the address of spaced allocated for "word_size".
// This methods does not know about blocks (Metablocks)
MetaWord* SpaceManager::allocate_work(size_t word_size) {
    assert_lock_strong(_lock);

    // Is there space in the current chunk?
    MetaWord* result = NULL;

    // For DumpSharedSpaces, only allocate out of the current chunk which is
    // never null because we gave it the size we wanted.   Caller reports out
    // of memory if this returns null.
    if (DumpSharedSpaces) {  //不进入,跳过
        assert(current_chunk() != NULL, "should never happen");
        inc_used_metrics(word_size);
        return current_chunk()->allocate(word_size); // caller handles null result
    }

    if (current_chunk() != NULL) { //到这里 Metachunk* current_chunk() const { return _current_chunk; }
        result = current_chunk()->allocate(word_size); //Metachunk* _current_chunk;
    }

    if (result == NULL) {
        result = grow_and_allocate(word_size);
    }

    if (result != NULL) {
        inc_used_metrics(word_size);
        assert(result != (MetaWord*) chunks_in_use(MediumIndex),
               "Head of the list is being allocated");
    }

    return result;
}

主程序进入灰色的函数,是这个Metachunk的类进行了内存分配

//接着进入
MetaWord* Metachunk::allocate(size_t word_size) { //word_size =12
    MetaWord* result = NULL;
    // If available, bump the pointer to allocate.
    if (free_word_size() >= word_size) {
        result = _top;
        _top = _top + word_size;
    }
    return result;
}

看下Metachunk对象的内存结构

(gdb) p/x _current_chunk
$5 = 0x7fd4b8800000
        (gdb) p/x * _current_chunk
$6 = {<Metabase<Metachunk>> = {_word_size = 0x80000, _next = 0x0, _prev = 0x0},
      _container = 0x7fd4c802e678,
      _top = 0x7fd4b88000a8,
      _is_tagged_free = 0x0}

查看Metachunk类的结果

 class Metachunk : public Metabase<Metachunk> {
     friend class TestMetachunk;

     // The VirtualSpaceNode containing this chunk.
     VirtualSpaceNode *_container;

     // Current allocation top.
     MetaWord *_top;
     ...省略方法
 }

进入黄色函数内部

进入free_word_size()  方法
        size_t Metachunk::free_word_size() const {
    return pointer_delta(end(), _top, sizeof(MetaWord));
} 

inline size_t pointer_delta(const void* left,
const void* right,
size_t element_size) {
return (((uintptr_t) left) - ((uintptr_t) right)) / element_size;
}

看的这里就知道了是用_current_chunk的end()-_top地址

//  Metachunk - Quantum of allocation from a Virtualspace
//    Metachunks are reused (when freed are put on a global freelist) and
//    have no permanent association to a SpaceManager.

//            +--------------+ <- end    --+       --+ 0x7fd4b8c00000
//            |              |             |         |
//            |              |             | free    |
//            |              |             |         |
//            |              |             |         | size | capacity
//            |              |             |         |
//            |              | <- top   -- +         |  0x7fd4b88000a8
//            |              |             |         |
//            |              |             | used    |
//            |              |             |         |
//            |              |             |         |
//            +--------------+ <- bottom --+       --+

看end()函数的实现,是在Metachunk的父类Metabase中定义的

class Metabase VALUE_OBJ_CLASS_SPEC {
  size_t _word_size;
  T*     _next;
  T*     _prev;

 protected:
size_t size() const volatile { return _word_size; } Metabase(size_t word_size) : _word_size(word_size), _next(NULL), _prev(NULL) {}
public:
.... uintptr_t
* end() const { return ((uintptr_t*) this) + size(); } ... };

那么这个end() 就是理解为Metabase的word_size=0x80000+ Metabase的地址 计算后得到 0x7fd4b8c00000

那么这个top就是Metachunk类中_top成员函数

接着进入红色函数

void SpaceManager::inc_used_metrics(size_t words) {
// Add to the per SpaceManager total
Atomic::add_ptr(words, &_allocated_blocks_words);
// Add to the global total
MetaspaceAux::inc_used(mdtype(), words);
}

其中查看内存

// Sum of all space in allocated chunks
size_t _allocated_blocks_words;  //15个


这条就牛逼了
Atomic::add_ptr(words, &_allocated_blocks_words); //word=12 ,
(gdb) p this
$25 = (SpaceManager * const) 0x7fd4c8050298
        (gdb) p _allocated_blocks_words
$26 = 15

进入分红函数

inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
    intptr_t addend = add_value;
    bool mp = os::is_MP();
    __asm__ __volatile__ (LOCK_IF_MP(%3) "xaddq %0,(%2)"
    : "=r" (addend)
    : "0" (addend), "r" (dest), "r" (mp)
    : "cc", "memory");
    return addend + add_value;
}

这个是内联汇编的打印汇编内容

//解释,这个是将12 加上 目标地址的值15,和为27,汇编指令为
(gdb) x/15i  $pc
=> 0x7fd4ce975528 <Atomic::add_ptr(long, long volatile*)+32>:    mov    -0x8(%rbp),%rax  //这个是参数1,为12
0x7fd4ce97552c <Atomic::add_ptr(long, long volatile*)+36>:    mov    -0x20(%rbp),%rdx     //这个是参数2,为指针地址
0x7fd4ce975530 <Atomic::add_ptr(long, long volatile*)+40>:    movzbl -0x9(%rbp),%ecx
0x7fd4ce975534 <Atomic::add_ptr(long, long volatile*)+44>:    cmp    $0x0,%cl
0x7fd4ce975537 <Atomic::add_ptr(long, long volatile*)+47>:    je     0x7fd4ce97553a <Atomic::add_ptr(long, long volatile*)+50>
0x7fd4ce975539 <Atomic::add_ptr(long, long volatile*)+49>:    lock xadd %rax,(%rdx)     //交换叫加,等价于 xchg eax,(),那么$rax=15,(%rdx)=12,然后$rax=27
0x7fd4ce97553e <Atomic::add_ptr(long, long volatile*)+54>:    mov    %rax,-0x8(%rbp)   将27 存到指针地址,即为参数2的地址,将和存入了_allocated_blocks_words
0x7fd4ce975542 <Atomic::add_ptr(long, long volatile*)+58>:    mov    -0x18(%rbp),%rax
0x7fd4ce975546 <Atomic::add_ptr(long, long volatile*)+62>:    mov    -0x8(%rbp),%rdx
0x7fd4ce97554a <Atomic::add_ptr(long, long volatile*)+66>:    add    %rdx,%rax
0x7fd4ce97554d <Atomic::add_ptr(long, long volatile*)+69>:    leaveq
0x7fd4ce97554e <Atomic::add_ptr(long, long volatile*)+70>:    retq

查看内存情况

(gdb) p this
$39 = (SpaceManager * const) 0x7fd4c8050298
        (gdb) p * this
$40 = (SpaceManager) {<CHeapObj<256u>> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7fd4cfa2c890 <vtable for SpaceManager+16>}, <No data fields>},
                      _lock = 0x7fd4c802e8f8,
                      _mdtype = Metaspace::NonClassType,
                      _chunks_in_use = {0x0, 0x0, 0x0, 0x7fd4b8800000},
                      _current_chunk = 0x7fd4b8800000,
                      static _small_chunk_limit = 4,
                      _allocated_blocks_words = 27,  //将上边的汇编操作将15变成了17
                      _allocated_chunks_words = 524288,
                      _allocated_chunks_count = 1,
                      _block_freelists = {_dictionary = 0x0, static WasteMultiplier = 4},
                      static _expand_lock_name = 0x7fd4cf466138 "SpaceManager chunk allocation lock",
                      static _expand_lock_rank = 3, static _expand_lock = 0x930758}
(gdb) p _vsm
$42 = (SpaceManager *) 0x7fd4c8050298,上面的就是这个_vsm
接着走流程  return result;  就是分配的top值
(gdb) p result
$43 = (MetaWord *) 0x7fd4b88000a8

这个对象上边的黄色函数跳出的结果

接着走流程进入最早的橘色2

// Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
copy.hpp
static void fill_to_aligned_words(HeapWord* to, size_t count, juint value = 0) {
assert_params_aligned(to);
pd_fill_to_aligned_words(to, count, value);
}

//copy_x86.cpp
static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) {
pd_fill_to_words(tohw, count, value);
}

static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
#ifdef AMD64
julong* to = (julong*) tohw;
  julong  v  = ((julong) value << 32) | value;
  while (count-- > 0) {
    *to++ = v;
  }
#else
juint* to = (juint*)tohw;
count *= HeapWordSize / BytesPerInt;
while (count-- > 0) {
*to++ = value;
}
#endif // AMD64
}

打印内存结构

(gdb) p tohw
$44 = (HeapWord *) 0x7fd4b88000a8
//以上是使用0 进行填充
(gdb) x/40x 0x7fd4b88000a8
0x7fd4b88000a8:    0x00000000    0x00000000    0x00000000    0x00000000
0x7fd4b88000b8:    0x00000000    0x00000000    0x00000000    0x00000000
0x7fd4b88000c8:    0x00000000    0x00000000    0x00000000    0x00000000
0x7fd4b88000d8:    0x00000000    0x00000000    0x00000000    0x00000000
0x7fd4b88000e8:    0x00000000    0x00000000    0x00000000    0x00000000
0x7fd4b88000f8:    0x00000000    0x00000000    0x00000000    0x00000000
0x7fd4b8800108:    0xf7f7f7f7    0xf7f7f7f7    0xf7f7f7f7    0xf7f7f7f7

 

至此就完成了 Array<u1>* 的12*8个字节的内存分配和初始化,即12个MetaWord

 

 

 

 

 

发表评论

0/200
198 点赞
0 评论
收藏
为你推荐 换一批