zoukankan      html  css  js  c++  java
  • jvm源码解读--03 常量池的解析ConstantPool

    先看bt栈

    (gdb) bt
    #0  ConstantPool::allocate (loader_data=0x7fe21802e868, length=87, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/oops/constantPool.cpp:47
    #1  0x00007fe2206d0bbc in ClassFileParser::parse_constant_pool (this=0x7fe22229a010, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:331
    #2  0x00007fe2206dce84 in ClassFileParser::parseClassFile (this=0x7fe22229a010, name=0x7fe21d4ad0e8, loader_data=0x7fe21802e868, protection_domain=..., host_klass=..., cp_patches=0x0, parsed_name=..., verify=false, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:3774
    #3  0x00007fe2206eb9b5 in ClassFileParser::parseClassFile (this=0x7fe22229a010, name=0x7fe21d4ad0e8, loader_data=0x7fe21802e868, protection_domain=..., parsed_name=..., verify=false, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.hpp:468
    #4  0x00007fe2206e97cb in ClassLoader::load_classfile (h_name=0x7fe21d4ad0e8, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classLoader.cpp:931
    #5  0x00007fe220d29903 in SystemDictionary::load_instance_class (class_name=0x7fe21d4ad0e8, class_loader=..., __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1304
    #6  0x00007fe220d27ced in SystemDictionary::resolve_instance_class_or_null (name=0x7fe21d4ad0e8, class_loader=..., protection_domain=..., __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:779
    #7  0x00007fe220d266be in SystemDictionary::resolve_or_null (class_name=0x7fe21d4ad0e8, class_loader=..., protection_domain=..., __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:232
    #8  0x00007fe220d2612f in SystemDictionary::resolve_or_fail (class_name=0x7fe21d4ad0e8, class_loader=..., protection_domain=..., throw_error=true, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:171
    #9  0x00007fe220d26451 in SystemDictionary::resolve_or_fail (class_name=0x7fe21d4ad0e8, throw_error=true, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:212
    #10 0x00007fe220d2b27b in SystemDictionary::initialize_wk_klass (id=SystemDictionary::Object_klass_knum, init_opt=0, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1866
    #11 0x00007fe220d2b39e in SystemDictionary::initialize_wk_klasses_until (limit_id=SystemDictionary::Cloneable_klass_knum, start_id=@0x7fe22229a9ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1882
    #12 0x00007fe220d2eb86 in SystemDictionary::initialize_wk_klasses_through (end_id=SystemDictionary::Class_klass_knum, start_id=@0x7fe22229a9ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.hpp:408
    #13 0x00007fe220d2b4d0 in SystemDictionary::initialize_preloaded_classes (__the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1901
    #14 0x00007fe220d2b19d in SystemDictionary::initialize (__the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1843
    #15 0x00007fe220d7c1d1 in Universe::genesis (__the_thread__=0x7fe21800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:288
    #16 0x00007fe220d7e439 in universe2_init () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:991
    #17 0x00007fe220917a5c in init_globals () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/init.cpp:114
    #18 0x00007fe220d5f756 in Threads::create_vm (args=0x7fe22229ae40, canTryAgain=0x7fe22229adff) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/thread.cpp:3424
    #19 0x00007fe2209ca232 in JNI_CreateJavaVM (vm=0x7fe22229ae88, penv=0x7fe22229ae80, args=0x7fe22229ae40) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/prims/jni.cpp:5166
    #20 0x00007fe221c67780 in InitializeJVM (pvm=0x7fe22229ae88, penv=0x7fe22229ae80, ifn=0x7fe22229ae90) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:1145
    #21 0x00007fe221c656f9 in JavaMain (_args=0x7ffe14eb62f0) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:371
    #22 0x00007fe221e81ea5 in start_thread () from /lib64/libpthread.so.0
    #23 0x00007fe22178a9fd in clone () from /lib64/libc.so.6

    进入这个函数

    ConstantPool*MetaWord(ClassLoaderData* loader_data, int length, TRAPS) {
      // Tags are RW but comment below applies to tags also.
      Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL);
    
      int size = ConstantPool::size(length); //length=87
    
      // CDS considerations:
      // Allocate read-write but may be able to move to read-only at dumping time
      // if all the klasses are resolved.  The only other field that is writable is
      // the resolved_references array, which is recreated at startup time.
      // But that could be moved to InstanceKlass (although a pain to access from
      // assembly code).  Maybe it could be moved to the cpCache which is RW.
      return new (loader_data, size, false, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
    }

    上篇写了关于 tags实现的内容

    现在解析一下size=的计算,

    static int header_size()             { return sizeof(ConstantPool)/HeapWordSize; } //计算结果为11
      static int size(int length)          { return align_object_size(header_size() + length); } //11+87 =98个
    
    inline bool is_object_aligned(intptr_t addr) {
      return addr == align_object_size(addr);//size=98
    }

    //在这个sizeof(ConstantPool) 计算出来的为1 不知道为什么,通过分析来得到大小

    //查看分配好的常量池
    (gdb) p * constant_pool
    $13 = (ConstantPool) {
                        <Metadata> = {<MetaspaceObj> = {<No data fields>},
                                        _vptr.Metadata = 0x7ff4c424c070 <vtable for ConstantPool+16>,
                                        _valid = 0},
                        _tags = 0x7ff4c01900a8,
                        _cache = 0x0,
                        _pool_holder = 0x0,
                        _operands = 0x0,
                        _resolved_references = 0x0,
                        _reference_map = 0x0,
                        _flags = 0,
                        _length = 87,
                        _saved = {_resolved_reference_length = 0, _version = 0},
                        _lock = 0x7ff4bc06ec38}
    (gdb) p sizeof(*constant_pool)
    $15 = 88

    这个通过对象来查看得到共有11项目,打印内存可以对应上

    (gdb) p constant_pool
    $1 = (ConstantPool *) 0x7f2563800108
    (gdb) x/22x 0x7f2563800108
    0x7f2563800108:    0x86b70070    0x00007f25    0x00000000    0x00000000
    0x7f2563800118:    0x638000a8    0x00007f25    0x00000000    0x00000000
    0x7f2563800128:    0x00000000    0x00000000    0x00000000    0x00000000
    0x7f2563800138:    0x00000000    0x00000000    0x00000000    0x00000000
    0x7f2563800148:    0x00000000    0x00000057    0x00000000    0x00000000
    0x7f2563800158:    0x8006ec38    0x00007f25

    需要特别说明的是: ConstantPool类里面有他的父类的,他的父类占用2个8字节空间,一个是虚表,一个是变量

    接着

    //进入重载new方法
    void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,
                                     size_t word_size, bool read_only,
                                     MetaspaceObj::Type type, TRAPS) throw() {
        // Klass has it's own operator new
        return Metaspace::allocate(loader_data, word_size, read_only,
                                   type, CHECK_NULL);
    }
    //进入元空间进行内存分配
    MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
                                  bool read_only, MetaspaceObj::Type type, TRAPS) {
        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.");
    
        MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : 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;
    }

    接着

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

    这里面设计一个指针加法,  _top + 8*word_size

    可以看出,_top(0x7fd4b8800108) + 98 最终等于 0x7fd4b8800418,是因为指针加法要乘 指针类型大小即8字节

    通过汇编验证

    (gdb) x/15i  $pc
    => 0x7fdfce6ef8df <Metachunk::allocate(unsigned long)+63>:    mov    0x20(%rax),%rax
    0x7fdfce6ef8e3 <Metachunk::allocate(unsigned long)+67>:    mov    -0x20(%rbp),%rdx
    0x7fdfce6ef8e7 <Metachunk::allocate(unsigned long)+71>:    shl    $0x3,%rdx
    0x7fdfce6ef8eb <Metachunk::allocate(unsigned long)+75>:    add    %rax,%rdx
    
    (gdb) p *(long *) ($rax+0x20)
    $15 = 140598841622792
            (gdb) p/x *(long *)($rax +0x20)
    $16 = 0x7fdfb802c108
            (gdb) p/x *(long * )($rbp -0x20)
    $17 = 0x62

    接着

    //看一个细节
     void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) {
         // _allocated_used_words tracks allocations for
         // each piece of metadata.  Those allocations are
         // generally done concurrently by different application
         // threads so must be done atomically.
         Atomic::add_ptr(words, &_allocated_used_words[mdtype]);
     }
     这个
     static size_t _allocated_used_words[Metaspace:: MetadataTypeCount];
    
    enum MetadataType {
        ClassType,
        NonClassType,
        MetadataTypeCount
    };

    具体为

    (gdb) p mdtype
    $9 = Metaspace::NonClassType
    
    (gdb) p/x _allocated_used_words[mdtype]
    $11 = 0x83
    这里是02
    那么整个过程由 0x21 变为了0x83 差值为0x62 十进制为98,和前面的98相同

    这里就完成了constant_pool的创建

  • 相关阅读:
    centos 7.0.1406 临时环境jenkins安装
    jenkins 登录提示无效
    ubuntu 16.04 安装完QQ后,更新或apt-get报错
    Web服务网站故障分析常用的命令
    在CentOS7中给docker加权限
    aliyun阿里云Maven仓库地址和其他地址
    python 安装 docker-copmose
    mysql 1055错误
    linux 添加用户
    firewall 开启服务
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14586604.html
Copyright © 2011-2022 走看看