zoukankan      html  css  js  c++  java
  • jvm源码解读--04 常量池 常量项的解析CONSTANT_Class_info

    接上篇的继续

      ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length,
                                                            CHECK_(nullHandle));
      _cp = constant_pool; // save in case of errors
      constantPoolHandle cp (THREAD, constant_pool);
    
      // parsing constant pool entries
      parse_constant_pool_entries(length, CHECK_(nullHandle));

    分析橘色的

    上面是一个构造方法

    定义中是带宏的,先看gdb打印类
    (gdb) ptype cp
    type = /* real type = constantPoolHandle */
    class constantPoolHandle : public StackObj {
    private:
        ConstantPool *_value;
        Thread *_thread;
    
    protected:
        ConstantPool * obj(void) const;
        ConstantPool * non_null_obj(void) const;
    public:
        constantPoolHandle(void);
        constantPoolHandle(ConstantPool *);
        constantPoolHandle(Thread *, ConstantPool *);
        constantPoolHandle(const constantPoolHandle &);
        constantPoolHandle & operator=(const constantPoolHandle &);
        ~constantPoolHandle();
        void remove(void);
        ConstantPool * operator()(void) const;
        ConstantPool * operator->(void) const;
        bool operator==(ConstantPool *) const;
        bool operator==(const constantPoolHandle &) const;
        bool is_null(void) const;
        bool not_null(void) const;
    }

    接着看宏定义

    在程序中是用宏定义的
    DEF_METADATA_HANDLE_FN(constantPool, ConstantPool)
    
    看下面的宏定义
    // Constructors for metadata handles
    #define DEF_METADATA_HANDLE_FN(name, type) \这里是初始化列表的构造方法,
    inline name##Handle::name##Handle(type* obj) : _value(obj), _thread(NULL) {
      if (obj != NULL) {                                                   
        assert(((Metadata*)obj)->is_valid(), "obj is valid");              
        _thread = Thread::current();                                       
        assert (_thread->is_in_stack((address)this), "not on stack?");     
        _thread->metadata_handles()->push((Metadata*)obj);                 
      }                                                                    
    }                                                                      
    inline name##Handle::name##Handle(Thread* thread, type* obj) : _value(obj), _thread(thread) { 
      if (obj != NULL) {                                                   
        assert(((Metadata*)obj)->is_valid(), "obj is valid");              
        assert(_thread == Thread::current(), "thread must be current");    
        assert (_thread->is_in_stack((address)this), "not on stack?");     
        _thread->metadata_handles()->push((Metadata*)obj);                 
      }                                                                    
    }

    在看实际解析

    (gdb) p cp
    $2 = (constantPoolHandle) {
        <StackObj> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7f2586b44390 <vtable for constantPoolHandle+16>}, <No data fields>},
       _value = 0x7f2563800108,
       _thread = 0x7f258000b800}
    接着进入的常量池条目解析
    // parsing constant pool entries
    parse_constant_pool_entries(length, CHECK_(nullHandle));
    
    //经典的 对象和指针
    ClassFileStream* cfs0 = stream();
    ClassFileStream cfs1 = *cfs0;
    ClassFileStream* cfs = &cfs1;

    先提供些定义

    enum {
        JVM_CONSTANT_Utf8 = 1,
        JVM_CONSTANT_Unicode,               /* unused */
        JVM_CONSTANT_Integer,                // 3
        JVM_CONSTANT_Float,                  // 4
        JVM_CONSTANT_Long,
        JVM_CONSTANT_Double,
        JVM_CONSTANT_Class,
        JVM_CONSTANT_String,
        JVM_CONSTANT_Fieldref,
        JVM_CONSTANT_Methodref,
        JVM_CONSTANT_InterfaceMethodref,
        JVM_CONSTANT_NameAndType,
        JVM_CONSTANT_MethodHandle           = 15,  // JSR 292
        JVM_CONSTANT_MethodType             = 16,  // JSR 292
        //JVM_CONSTANT_(unused)             = 17,  // JSR 292 early drafts only
        JVM_CONSTANT_InvokeDynamic          = 18,  // JSR 292
        JVM_CONSTANT_ExternalMax            = 18   // Last tag found in classfiles
    };

    还有

    CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
    }
    
    CONSTANT_Integer_info {
    u1 tag;
    u4 bytes;
    }
    
    CONSTANT_Float_info {
    u1 tag;
    u4 bytes;
    }
    
    CONSTANT_Long_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
    }
    
    CONSTANT_Double_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
    }
    
    CONSTANT_Class_info {
    u1 tag;
    u2 name_index;
    }
    
    
    CONSTANT_String_info {
    u1 tag;
    u2 string_index;
    }
    
    CONSTANT_Fieldref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
    }
    
    CONSTANT_Methodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
    }
    
    CONSTANT_InterfaceMethodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
    }
    
    CONSTANT_NameAndType_info {
    u1 tag;
    u2 name_index;
    u2 descriptor_index;
    }
    
    
    CONSTANT_MethodHandle_info {
    u1 tag;
    u1 reference_kind;
    u2 reference_index;
    }
    
    CONSTANT_MethodType_info {
    u1 tag;
    u2 descriptor_index;
    }
    
    CONSTANT_InvokeDynamic_info {
    u1 tag;
    u2 bootstrap_method_attr_index;
    u2 name_and_type_index;
    }

    进入函数

     // parsing  Index 0 is unused
      for (int index = 1; index < length; index++) {
        // Each of the following case guarantees one more byte in the stream
        // for the following tag or the access_flags following constant pool,
        // so we don't need bounds-check for reading tag.
        u1 tag = cfs->get_u1_fast();
        switch (tag) {
          case JVM_CONSTANT_Class :
            {
              cfs->guarantee_more(3, CHECK);  // name_index, tag/access_flags
              u2 name_index = cfs->get_u2_fast();
              _cp->klass_index_at_put(index, name_index);
            }
            break;
          case JVM_CONSTANT_Fieldref :
            {
              cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags
              u2 class_index = cfs->get_u2_fast();
              u2 name_and_type_index = cfs->get_u2_fast();
              _cp->field_at_put(index, class_index, name_and_type_index);
            }
            break;
    ....
    }

    蓝色的过程就是取出tag的值

    看执行前

    先看下cfs 对象
            (gdb) p cfs
    $4 = (ClassFileStream *) 0x7f2587845460
            (gdb) p * cfs
    $5 = (ClassFileStream) {<ResourceObj> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7f2586b588b0 <vtable for ClassFileStream+16>}, _allocation_t = {18446604274545437599, 0}},
                            _buffer_start = 0x7f258000ea28 "312376272276",
                            _buffer_end = 0x7f258000f0ee "253253253253253253253253253253260210265206%177",
                            _current = 0x7f258000ea32 "a",
                            _source = 0x7f258006eb98 "/home/atzhang/atzhang/openjdksource/openjdk8/openjdk/build/linux-x86_64-normal-server-slowdebug/jdk/classes", _need_verify = false}
    
    (gdb) x/10x cfs->_current
    0x7f258000ea32:    0x0a3a0007    0x3b000100    0x0012000a    0x3d000a3c
    0x7f258000ea42:    0x000a3e00    0x083f0001    0x000a4000    0x0a410012
    0x7f258000ea52:    0x43004200    0x0001000a

    那么取出来u1 就是07 

    进入switch tag=7 对应的是

    CONSTANT_Class_info {
    u1 tag;
    u2 name_index;
    }
    与下面的逻辑相应
          case JVM_CONSTANT_Class :
            {
              cfs->guarantee_more(3, CHECK);  // name_index, tag/access_flags
              u2 name_index = cfs->get_u2_fast();
              _cp->klass_index_at_put(index, name_index);
            }

    取u2 =58  对应内存标注蓝色的0x3a

    进入黄色函数之前的定义有

    enum {
        // See jvm.h for shared JVM_CONSTANT_XXX tags
        // NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/utilities/ConstantTag.java
        // Hotspot specific tags
        JVM_CONSTANT_Invalid                  = 0,    // For bad value initialization
        JVM_CONSTANT_InternalMin              = 100,  // First implementation tag (aside from bad value of course)
        JVM_CONSTANT_UnresolvedClass          = 100,  // Temporary tag until actual use
        JVM_CONSTANT_ClassIndex               = 101,  // Temporary tag while constructing constant pool
        JVM_CONSTANT_StringIndex              = 102,  // Temporary tag while constructing constant pool
        JVM_CONSTANT_UnresolvedClassInError   = 103,  // Error tag due to resolution error
        JVM_CONSTANT_MethodHandleInError      = 104,  // Error tag due to resolution error
        JVM_CONSTANT_MethodTypeInError        = 105,  // Error tag due to resolution error
        JVM_CONSTANT_InternalMax              = 105   // Last implementation tag
    };

    进入黄色函数

    // For temporary use while constructing constant pool
    void klass_index_at_put(int which, int name_index) {
        tag_at_put(which, JVM_CONSTANT_ClassIndex);
        *int_at_addr(which) = name_index;
    }
    
    void tag_at_put(int which, jbyte t)          { tags()->at_put(which, t); }
    Array<u1>* tags() const                   { return _tags; }
    void at_put(const int i, const T& x) { assert(i >= 0 && i< _length, err_msg("oob: 0 <= %d < %d", i, _length)); _data[i] = x; }

    能看到粉色函数是将tags数组索引为1的值设为了101 (JVM_CONSTANT_ClassIndex = 101)

    使用内存验证

    执行前
    (gdb) x/10x _data
    0x7f25638000ac:    0x00000000    0x00000000    0x00000000    0x00000000
    0x7f25638000bc:    0x00000000    0x00000000    0x00000000    0x00000000
    0x7f25638000cc:    0x00000000    0x00000000
    
    执行后
    (gdb) x/10x _tags._data
    0x7f25638000ac:    0x00006500    0x00000000    0x00000000    0x00000000
    0x7f25638000bc:    0x00000000    0x00000000    0x00000000    0x00000000
    0x7f25638000cc:    0x00000000    0x00000000

    进入灰色函数

    jint* int_at_addr(int which) const {
        assert(is_within_bounds(which), "index out of bounds");
        return (jint*) &base()[which];
    }
    
    intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); }

    解析这个,

    //解释  (gdb) p this
    //$16 = (const ConstantPool * const) 0x7f2563800108
    这里要转换,转换为(char*)指针类型的做加法 + {sizeof(ConstantPool)=88} 就是加88个字节,要是 (long*)类型的加法就会+88*8 了
    (gdb) p (jint*) &base()[0]
    $20 = (jint *) 0x7f2563800160
    (gdb) p (jint*) &base()[which]
    $19 = (jint *) 0x7f2563800168 ,这里which等于1,所以移动了8位
    实际实现的就是将index=58 存放到了0x7f2563800168,这个地方了,这个地方之前,内存分配的时候为87个变量每个变量分配了一个8字节的空间
    那么就是将58 这个变量放到了那个地址中

    内存情况
    (gdb) p *0x7f2563800168
    $21 = 0
            执行后
    (gdb) p *0x7f2563800168
    $22 = 58
     
  • 相关阅读:
    ppa 安装gnome3
    Ubuntu 升级VisualBox后无法启动 Kernel driver not installed (rc=-1908)
    ubuntu 安装 n卡 驱动
    apt-get 介绍。
    linux流量查看工具 iftop
    Ubuntu防火墙 UFW 设置
    Linux Shell快捷键(基本是通用的)
    gnome3 shell快捷键
    day2 -- 字符串常用方法、列表、字典
    day1 -- Python变量、注释、格式化输出字符串、input、if、while、for
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14591130.html
Copyright © 2011-2022 走看看