美文网首页
oop_iterate

oop_iterate

作者: 程序员札记 | 来源:发表于2022-12-13 08:54 被阅读0次

    GC引用遍历时最终都会碰到oopDesc::oop_iterate这个方法,用来遍历该对象所引用的其他对象,本篇博客就来详细探讨这个关键方法的实现。

    1、oopDesc::oop_iterate/ oopDesc::oop_iterate_backwards
    oopDesc定义的oop遍历的方法主要就上述两个,oop_iterate有两个版本,一个只有一个参数OopClosure,另外一个有两个参数,OopClosure和MemRegion。这两方法都是通过宏定义的,位于hotspot\src\share\vm\oops\oop.hpp中,如下:

    #define OOP_ITERATE_DECL(OopClosureType, nv_suffix)                      \
      int oop_iterate(OopClosureType* blk);                                  \
      int oop_iterate(OopClosureType* blk, MemRegion mr);  // Only in mr.
      
      //ALL_OOP_OOP_ITERATE_CLOSURES_1用来定义具体的OopClosureType
      //OOP_ITERATE_DECL就是定义具体的方法
      ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL)
      ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL)
     
    #if INCLUDE_ALL_GCS
     
    #define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix)            \
      int oop_iterate_backwards(OopClosureType* blk);
     
      ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DECL)
      ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DECL)
    #endif
    
     这两方法的实现在同目录下的oop.inline.hpp中,如下:
    
     
    #define OOP_ITERATE_DEFN(OopClosureType, nv_suffix)                        \
                                                                               \
    inline int oopDesc::oop_iterate(OopClosureType* blk) {                     \
      SpecializationStats::record_call();                                      \
      return klass()->oop_oop_iterate##nv_suffix(this, blk);               \
    }                                                                          \
                                                                               \
    inline int oopDesc::oop_iterate(OopClosureType* blk, MemRegion mr) {       \
      SpecializationStats::record_call();                                      \
      return klass()->oop_oop_iterate##nv_suffix##_m(this, blk, mr);       \
    }
     
    //ALL_OOP_OOP_ITERATE_CLOSURES_1定义具体的OopClosureType
    ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DEFN)
     
    #define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix)              \
                                                                               \
    inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) {           \
      SpecializationStats::record_call();                                      \
      return klass()->oop_oop_iterate_backwards##nv_suffix(this, blk);     \
    }
     
    ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DEFN)
    

    oopDesc的其他几个子类可以参考Hotspot Oop模型——Java对象内存表示机制,其他子类没有覆写父类oopDesc的oop_iterate方法的实现,只有表示对象数组的objArrayOopDesc新增了一个oop_iterate_range方法,定义在同目录的objArrayOop.hpp中,如下:


    image.png

    其实现在在同目录的objArrayOop.cpp中,如下:

    image.png

    即oopDesc的引用遍历方法底层都是调用Klass的相关方法。

    2、Klass::oop_oop_iterate / Klass::oop_oop_iterate_backwards
    这两组方法的定义方式跟oopDesc是一样的,定义在同目录的klass.hpp中,如下:

    //oopDesc::oop_iterate对应的两个方法
    define Klass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix)                \
      virtual int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk) {     \
        /* Default implementation reverts to general version. */                 \
        return oop_oop_iterate(obj, blk);                                        \
      }                                                                          \
                                                                                 \
      virtual int oop_oop_iterate##nv_suffix##_m(oop obj,                        \
                                                 OopClosureType* blk,            \
                                                 MemRegion mr) {                 \
        return oop_oop_iterate_m(obj, blk, mr);                                  \
      }
     
      //同样,SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1用来定义具体类型的OopClosureType
      SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL)
      SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL)
     
    #if INCLUDE_ALL_GCS
    //oopDesc::oop_iterate_backwards对应的方法实现
    #define Klass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix)      \
      virtual int oop_oop_iterate_backwards##nv_suffix(oop obj,                  \
                                                       OopClosureType* blk) {    \
        /* Default implementation reverts to general version. */                 \
        return oop_oop_iterate_backwards_v(obj, blk);                            \
      }
     
      SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL)
      SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL)
    #endif // INCLUDE_ALL_GCS
    

    在Eclipse中点击oop_oop_iterate方法的实现如下:

    image.png

    即不同的Klass子类都有自己的实现版本,其中Klass的实现是一个虚方法,空实现。oop_oop_iterate_m和oop_oop_iterate_backwards_v的实现都一样取决于子类。Klass的各子类的说明参考《Hotspot Klass模型——Java类内存表示机制》,下面逐一讲解各子类的实现。

    3、InstanceKlass
    InstanceKlass用于表示普通的Java类,该类重定义了oop_oop_iterate和oop_oop_iterate_backwards方法,如下:

    image.png

    这里用于表示具体的OopClosureType的宏跟oopDesc中使用的宏是一样的,即跟oopDesc中定义的方法是能一一对应的,其实现如下:

    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN)
     
    #define InstanceKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)        \
                                                                                 \
    int InstanceKlass::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik);\
      /* header */                                                          \
      if_do_metadata_checked(closure, nv_suffix) {                          \
        //如果需要检查Klass,则遍历该klass
        closure->do_klass##nv_suffix(obj->klass());                         \
      }                                                                     \
      InstanceKlass_OOP_MAP_ITERATE(                                        \
        obj,                                                                \
        SpecializationStats::                                               \
          record_do_oop_call##nv_suffix(SpecializationStats::ik);           \
        (closure)->do_oop##nv_suffix(p),                                    \//注意这里是两个方法作为参数do_oop传入到宏中的
        assert_is_in_closed_subset)                                         \
      return size_helper();                                                 \
    }
     
    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN_m)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN_m)
     
    #define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
                                                                            \
    int InstanceKlass::oop_oop_iterate##nv_suffix##_m(oop obj,              \
                                                      OopClosureType* closure, \
                                                      MemRegion mr) {          \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik);\
      if_do_metadata_checked(closure, nv_suffix) {                           \
        if (mr.contains(obj)) {                                              \
          //如果需要检查Klass,则遍历该klass
          closure->do_klass##nv_suffix(obj->klass());                        \
        }                                                                    \
      }                                                                      \
      InstanceKlass_BOUNDED_OOP_MAP_ITERATE(                                 \
        obj, mr.start(), mr.end(),                                           \
        (closure)->do_oop##nv_suffix(p),                                     \
        assert_is_in_closed_subset)                                          \
      return size_helper();                                                  \
    }
     
    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
     
    #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                    \
    int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj,                \
                                                  OopClosureType* closure) {        \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik); \
      //校验closure的do_metadata方法返回false                                                                            \
      assert_should_ignore_metadata(closure, nv_suffix);                            \
                                                                                    \
      /* instance variables */                                                      \
      InstanceKlass_OOP_MAP_REVERSE_ITERATE(                                        \
        obj,                                                                        \
        SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::ik);\
        (closure)->do_oop##nv_suffix(p),                                            \
        assert_is_in_closed_subset)                                                 \
       return size_helper();                                                        \
    }
     
    #define if_do_metadata_checked(closure, nv_suffix)       \
      /* Make sure the non-virtual and the virtual versions match. */     \
      assert(closure->do_metadata##nv_suffix() == closure->do_metadata(), \
          "Inconsistency in do_metadata");                                \
      if (closure->do_metadata##nv_suffix()) //判断是否需要检查klass
     
    //返回该对象的大小
    int size_helper() const {
        return layout_helper_to_size_helper(layout_helper());
      }
     
    #define assert_should_ignore_metadata(closure, nv_suffix)                                  \
      assert(!closure->do_metadata##nv_suffix(), "Code to handle metadata is not implemented")
     
    #define InstanceKlass_OOP_MAP_ITERATE(obj, do_oop, assert_fn)            \
    {                                                                        \
      /*计算包含所引用的oop的起止范围*/                                  \
      OopMapBlock* map           = start_of_nonstatic_oop_maps();            \
      OopMapBlock* const end_map = map + nonstatic_oop_map_count();          \
      if (UseCompressedOops) {                                               \
        while (map < end_map) {                                              \
          InstanceKlass_SPECIALIZED_OOP_ITERATE(narrowOop,                   \
            obj->obj_field_addr<narrowOop>(map->offset()), map->count(),     \
            do_oop, assert_fn)                                               \
          ++map;                                                             \
        }                                                                    \
      } else {                                                               \
        //注意外层是遍历OopMapBlock
        while (map < end_map) {                                              \
          //InstanceKlass_SPECIALIZED_OOP_ITERATE遍历某个Map内包含的oop
          InstanceKlass_SPECIALIZED_OOP_ITERATE(oop,                         \
            //map->offset()返回第一个引用类型属性相当于当前oop的偏移量
            //map->count()返回该Map包含的oop的个数
            obj->obj_field_addr<oop>(map->offset()), map->count(),           \
            do_oop, assert_fn)                                               \
          ++map;                                                             \
        }                                                                    \
      }                                                                      \
    }
     
    //返回当前Klass的OopMapBlock的起始位置,itable的起始地址加上itable的长度就是OopMapBlock的起始地址了
    OopMapBlock* start_of_nonstatic_oop_maps() const {
        return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
      }
     
    //返回vtable的起始问题
    intptr_t* start_of_vtable() const        { return ((intptr_t*)this) + vtable_start_offset(); }
     
    //vtable的起始位置加上vtable的长度就是itable的起始地址了
    intptr_t* start_of_itable() const        { return start_of_vtable() + align_object_offset(vtable_length()); }
     
    //返回包含的OopMapBlock的个数
    unsigned int nonstatic_oop_map_count() const {
        return _nonstatic_oop_map_size / OopMapBlock::size_in_words();
      }
     
    //获取相当于当前oop地址指定偏移量的属性地址
    template <class T> inline T* oopDesc::obj_field_addr(int offset) const { return (T*)field_base(offset); }
     
    inline void*     oopDesc::field_base(int offset)        const { return (void*)&((char*)this)[offset]; }
     
     
    #define InstanceKlass_SPECIALIZED_OOP_ITERATE( \
      T, start_p, count, do_oop,                \
      assert_fn)                                \
    {                                           \
      T* p         = (T*)(start_p);             \
      T* const end = p + (count);               \
      //遍历指定范围的oop
      while (p < end) {                         \
        (assert_fn)(p);                         \
        do_oop;                                 \
        ++p;                                    \
      }                                         \
    }
     
    //low和high就是MemRegion的起始位置
    #define InstanceKlass_BOUNDED_OOP_MAP_ITERATE(obj, low, high, do_oop,    \
                                                  assert_fn)                 \
    {                                                                        \
      OopMapBlock* map           = start_of_nonstatic_oop_maps();            \
      OopMapBlock* const end_map = map + nonstatic_oop_map_count();          \
      if (UseCompressedOops) {                                               \
        while (map < end_map) {                                              \
          InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop,           \
            obj->obj_field_addr<narrowOop>(map->offset()), map->count(),     \
            low, high,                                                       \
            do_oop, assert_fn)                                               \
          ++map;                                                             \
        }                                                                    \
      } else {                                                               \
        while (map < end_map) {                                              \
          InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,                 \
            obj->obj_field_addr<oop>(map->offset()), map->count(),           \
            low, high,                                                       \
            do_oop, assert_fn)                                               \
          ++map;                                                             \
        }                                                                    \
      }                                                                      \
    }
     
    #define InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE( \
      T, start_p, count, low, high,             \
      do_oop, assert_fn)                        \
    {                                           \
      T* const l = (T*)(low);                   \
      T* const h = (T*)(high);                  \
      //校验l和h都是按照T的大小的整数倍,即已经内存对齐了
      assert(mask_bits((intptr_t)l, sizeof(T)-1) == 0 && \
             mask_bits((intptr_t)h, sizeof(T)-1) == 0,   \
             "bounded region must be properly aligned"); \
      T* p       = (T*)(start_p);               \
      T* end     = p + (count);                 \
      //计算遍历对象的地址范围
      if (p < l) p = l;                         \
      if (end > h) end = h;                     \
      while (p < end) {                         \
        (assert_fn)(p);                         \
        do_oop;                                 \
        ++p;                                    \
      }                                         \
    }
     
    //注意跟InstanceKlass_OOP_MAP_ITERATE相比,此处从外层都内层都是从高地址往低地址反向遍历
    #define InstanceKlass_OOP_MAP_REVERSE_ITERATE(obj, do_oop, assert_fn)    \
    {                                                                        \
      OopMapBlock* const start_map = start_of_nonstatic_oop_maps();          \
      OopMapBlock* map             = start_map + nonstatic_oop_map_count();  \
      if (UseCompressedOops) {                                               \
        while (start_map < map) {                                            \
          --map;                                                             \
          InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE(narrowOop,           \
            obj->obj_field_addr<narrowOop>(map->offset()), map->count(),     \
            do_oop, assert_fn)                                               \
        }                                                                    \
      } else {                                                               \
        while (start_map < map) {                                            \
          --map;                                                             \
          InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE(oop,                 \
            obj->obj_field_addr<oop>(map->offset()), map->count(),           \
            do_oop, assert_fn)                                               \
        }                                                                    \
      }                                                                      \
    }
     
    //注意此方法是从高地址往地址反向遍历
    #define InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE( \
      T, start_p, count, do_oop,                \
      assert_fn)                                \
    {                                           \
      T* const start = (T*)(start_p);           \
      T*       p     = start + (count);         \
      while (start < p) {                       \
        --p;                                    \
        (assert_fn)(p);                         \
        do_oop;                                 \
      }                                         \
    }
    

    从上述实现可知每个oop的vtable的后面都包含有若干个OopMapBlock,每个OopMapBlock都保存了若干个oop,InstanceKlass的oop_oop_iterate方法实际就是遍历所有OopMapBlock中包含的oop。

    4、OopMapBlock
    OopMapBlock是一个简单的内嵌在Klass里面的数据结构,用来描述oop中包含的引用类型属性,即该oop所引用的其他oop在oop中的内存分布,然后就可以根据当前oop的地址找到所有引用的其他oop了,其定义如下:

    image.png

    其中offset描述第一个所引用的oop相对于当前oop地址的偏移量,count表示包含的oop的个数,注意这里的包含并不是指这些oop位于OopMapBlock里面,而是有count个连续存放的oop。为啥会有多个OopMapBlock了?因为每个OopMapBlock只能描述当前子类中包含的引用类型属性,父类的引用类型属性由单独的OopMapBlock描述,下面我们用HSDB来实际探查下,HSDB的使用可以参考《Hotspot学习利器:HSDB和CLHSDB》。测试用例如下:

    package jvmTest;
     
    import java.lang.management.ManagementFactory;
    import java.lang.management.RuntimeMXBean;
     
    class Base{
        private int a=1;
     
        private String s="abc";
     
        private Integer a2=12;
     
        private int a3=22;
    }
     
    class A extends Base  {
        private int b=3;
     
        private String s2="def";
     
        private int b2=33;
     
        private Base a=new Base();
    }
     
    class B extends A{
        private String s3="ghk";
     
        private Integer c=4;
     
        private int c2=44;
    }
     
    public class MainTest {
     
        public static void main(String[] args) {
            Base a=new Base();
            A a2=new A();
            B b=new B();
            while (true){
                try {
                    System.out.println(getProcessID());
                    Thread.sleep(600*1000);
                } catch (Exception e) {
     
                }
            }
        }
     
        public static final int getProcessID() {
            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            System.out.println(runtimeMXBean.getName());
            return Integer.valueOf(runtimeMXBean.getName().split("@")[0])
                    .intValue();
        }
    }
    

    运行main方法后,用HSDB查看main线程的线程栈,从中找出变量a,a2,b对应的oop的地址,如下:


    image.png

    分别查看0x00000000d69d98a0,0x00000000d69db5f8,0x00000000d69dd070对应的oop,如下:


    image.png image.png image.png

    上从面的截图可知,子类会完整的保留父类的属性,从而方便调用父类方法时能够正确的使用父类的属性。上述对oop的属性打印是按照类声明属性的顺序来的,内存中是这样保存的么?可以通过查看属性的偏移量来判断。

    在Class Browser中搜索jvmTest,可以查找到我们三个自定义类对应的Klass,如下图:


    image.png

    分别点击这三个类查看属性的偏移量,如下:


    image.png image.png image.png

    根据上述偏移量,我们可以得出jvmTest.B对象的内存布局,如下:

    image.png

    int本身占4个字节,引用类型属性本质上就是一个指针,这里因为默认开启了指针压缩,所以也是4字节。

    我们再看下表示OopMapBlock在Klass中的字宽数的属性_nonstatic_oop_map_size在三个类中的取值,如下:

    image.png image.png image.png

    OopMapBlock本身就只有两个int属性,所以一个OopMapBlock实例只有8字节,即一个字宽,jvmTest.B的_nonstatic_oop_map_size属性值为3,即由3个OopMapBlock,下面通过CHSDB的mem命令来看看这3个OopMapBlock对应的内存数据。

    首先执行inspect对象得到该Klass本身的大小,即sizeof的大小,如下:


    image.png

    vtable,itable,OopMapBlock这三个都是内嵌在Klass里面的,所谓的内嵌实际是指这块内存是紧挨着Klass自身的属性对应的内存的下面,从上一节的分析可知,OopMapBlock在itable的后面,itable在vtable的后面,而vtable是紧挨着Klass的,从上述inspect命令的输出,也可知道itable和vtable的内存大小,单位是字宽,如下:

    image.png

    因此OopMapBlock的起始地址就是Klass的地址加上Klass本身的大小440字节即55字宽,再加上vtable的5字宽,itable的2字宽,总共加62字宽,OopMapBlock本身占用3个字宽,因此用mem查看这65字宽的数据,如下:


    image.png

    最后的3个字宽如下:

    image.png

    每个字宽对应一个OopMapBlock,前面4字节就是count属性,这里都是2,后面4字节就是offset,分别是20,36,48,与jvmTest.B的内存结构是完全一致的。

    5、InstanceClassLoaderKlass
    InstanceClassLoaderKlass继承自InstanceKlass,用来表示java.lang.ClassLoader及其子类的Klass,该类没有新增其他的属性,主要是改写了引用遍历的方法的实现,增加了对ClassLoaderData的遍历,定义如下:

    image.png

    其实现如下:

    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN)
     
    #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)\
                                                                                    \
    int InstanceClassLoaderKlass::                                                  \
    oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) {                  \
      /* Get size before changing pointers */                                       \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
      int size = InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure);           \
                                                                                    \
      //如果需要遍历                                                                              
      if_do_metadata_checked(closure, nv_suffix) {                                  \
        ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);             \
        if (cld != NULL) {                                                          \
          //遍历ClassLoaderData
          closure->do_class_loader_data(cld);                                       \
        }                                                                           \
      }                                                                             \
                                                                                    \
      return size;                                                                  \
    }
     
    //返回ClassLoader oop对应的ClassLoaderData指针
    ClassLoaderData* java_lang_ClassLoader::loader_data(oop loader) {
      return *java_lang_ClassLoader::loader_data_addr(loader);
    }
     
    ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) {
        assert(loader != NULL && loader->is_oop(), "loader must be oop");
        //_loader_data_offset是一个静态属性,值为-1,即ClassLoaderData指针保存在ClassLoader oop的前一个字节中
        return (ClassLoaderData**) loader->address_field_addr(_loader_data_offset);
    }
     
    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
     
    #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)      \
                                                                                    \
    int InstanceClassLoaderKlass::                                                  \
    oop_oop_iterate##nv_suffix##_m(oop obj,                                         \
                                   OopClosureType* closure,                         \
                                   MemRegion mr) {                                  \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
                                                                                    \
      int size = InstanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr);   \
                                                                                    \
      if_do_metadata_checked(closure, nv_suffix) {                                  \
        if (mr.contains(obj)) {                                                     \
          ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);           \
          if (cld != NULL) {                                                        \
            //遍历ClassLoaderData
            closure->do_class_loader_data(cld);                                     \
          }                                                                         \
        }                                                                           \
      }                                                                             \
                                                                                    \
      return size;                                                                  \
    }
     
    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
     
    #if INCLUDE_ALL_GCS
    #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                    \
    int InstanceClassLoaderKlass::                                                  \
    oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) {        \
      /* Get size before changing pointers */                                       \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
      int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
      return size;                                                                  \
    }
    #endif // INCLUDE_ALL_GCS
    

    6、InstanceMirrorKlass
    InstanceMirrorKlass继承自InstanceKlass,用来表示java.lang.Class这个特殊类的Klass,注意java.lang.Class是一个final类,不能被继承。每个类的静态属性就是由该Klass对应的oop来维护的,创建该oop时必须通过InstanceMirrorKlass创建,该类改写了计算oop大小的方法,会把InstanceKlass中保存的静态属性的字宽数(_static_field_size属性)算进来,可通过Klass的_java_mirror属性来访问该oop,注意各种类的Class实例如String.class对应的oop的klass都指向同一个InstanceMirrorKlass实例。Class类实例的创建是通过InstanceMirrorKlass::allocate_instance完成的,该方法的实现如下:

    instanceOop InstanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) {
      //计算实例大小
      int size = instance_size(k);
      KlassHandle h_k(THREAD, this);
      //内存分配
      instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
      //设置实例大小,将size保存到oop中的oop_size字段中
      java_lang_Class::set_oop_size(i, size);
     
      return i;
    }
    int InstanceMirrorKlass::instance_size(KlassHandle k) {
      //校验k是一个非数组类Klass,通过_layout_helper的取值判断,如果是数组,该属性是一个负值
      if (k() != NULL && k->oop_is_instance()) {
        //static_field_size记录该类的静态字段的大小,单位也是字宽
        return align_object_size(size_helper() + InstanceKlass::cast(k())->static_field_size());
      }
      return size_helper();
    }
     
      int size_helper() const {
        return layout_helper_to_size_helper(layout_helper());
      }
     
      //_layout_helper保存该类Klass对应的oop的大小,是根据oop包含的对象头和字段属性在class文件解析的时候计算出来的
      int layout_helper() const            { return _layout_helper; }
     
      static int layout_helper_to_size_helper(jint lh) {
        assert(lh > (jint)_lh_neutral_value, "must be instance");
        //LogHeapWordSize表示一个字段对应的字节数的log值,64位下是3,这里相当于按8整除
        return lh >> LogHeapWordSize;
      }
     
      int static_field_size() const            { return _static_field_size; }
     
    void java_lang_Class::set_oop_size(oop java_class, int size) {
      assert(_oop_size_offset != 0, "must be set");
      java_class->int_field_put(_oop_size_offset, size);
    }
    

    该类主要改写了计算oop大小和引用遍历的相关方法,因为必须考虑类的静态属性。引用遍历的方法定义如下:

    image.png

    其实现如下:

    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
     
    #define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)           \
                                                                                          \
    int InstanceMirrorKlass::                                                             \
    oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) {                        \
      /* Get size before changing pointers */                                             \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);      \
                                                                                          \
      //遍历Class实例本身的都有的属性,这些属性是隐藏的,无法通过反射查看并修改                                                                                    
      InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure);                            \
                                                                                          \
      if_do_metadata_checked(closure, nv_suffix) {                                        \
        //获取对应的Klass
        Klass* klass = java_lang_Class::as_Klass(obj);                                    \
        if (klass != NULL) {                                                              \
          //遍历Klass,实际就是遍历对应的ClassLoaderData
          closure->do_klass##nv_suffix(klass);                                            \
        }                                                                                 \
      }                                                                                   \
                                                                                          \
      //遍历静态类型属性                                                                                    
      if (UseCompressedOops) {                                                            \
        InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(narrowOop, nv_suffix);           \
      } else {                                                                            \
        InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix);                 \
      }                                                                                   \
    }
     
    Klass* java_lang_Class::as_Klass(oop java_class) {
      //校验该oop是一个java_lang_Class实例
      assert(java_lang_Class::is_instance(java_class), "must be a Class object");
      //获取该Class实例对应的类的Klass,对应的klass实际作为一个隐藏的属性保存在该oop里面
      Klass* k = ((Klass*)java_class->metadata_field(_klass_offset));
      assert(k == NULL || k->is_klass(), "type check");
      return k;
    }
     
    static bool is_instance(oop obj) {
        //Class_klass就是java_lang_Class对一个的Klass,即InstanceMirrorKlass
        return obj != NULL && obj->klass() == SystemDictionary::Class_klass();
      }
     
    #define InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(T, nv_suffix)                \
      InstanceMirrorKlass_OOP_ITERATE(                                                    \
        start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj),        \
          (closure)->do_oop##nv_suffix(p),                                                \
        assert_is_in_closed_subset)                                                       \
      return oop_size(obj);   
     
    //获取静态的引用类型属性在Class实例中的起始地址
    static HeapWord* start_of_static_fields(oop obj) {
        return (HeapWord*)(cast_from_oop<intptr_t>(obj) + offset_of_static_fields());
      }
     
    static int offset_of_static_fields() {
        return _offset_of_static_fields;
      }
     
    //获取包含的静态oop的个数
    int  java_lang_Class::static_oop_field_count(oop java_class) {
      assert(_static_oop_field_count_offset != 0, "must be set");
      return java_class->int_field(_static_oop_field_count_offset);
    }
     
    #define InstanceMirrorKlass_OOP_ITERATE(start_p, count,    \
                                      do_oop, assert_fn)       \
    {                                                          \
      if (UseCompressedOops) {                                 \
        InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
          start_p, count,                                      \
          do_oop, assert_fn)                                   \
      } else {                                                 \
        InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE(oop,       \
          start_p, count,                                      \
          do_oop, assert_fn)                                   \
      }                                                        \
    }
     
    //遍历从start_p开始的count个oop
    #define InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE( \
      T, start_p, count, do_oop,                         \
      assert_fn)                                         \
    {                                                    \
      T* p         = (T*)(start_p);                      \
      T* const end = p + (count);                        \
      while (p < end) {                                  \
        (assert_fn)(p);                                  \
        do_oop;                                          \
        ++p;                                             \
      }                                                  \
    }
     
    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
     
    #define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)         \
                                                                                          \
    int InstanceMirrorKlass::                                                             \
    oop_oop_iterate##nv_suffix##_m(oop obj,                                               \
                                   OopClosureType* closure,                               \
                                   MemRegion mr) {                                        \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);      \
                                                                                          \
      InstanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr);                    \
                                                                                          \
      if_do_metadata_checked(closure, nv_suffix) {                                        \
        if (mr.contains(obj)) {                                                           \
          //获取对应的Klass
          Klass* klass = java_lang_Class::as_Klass(obj);                                  \
          if (klass != NULL) {                                                            \
            //遍历Klass
            closure->do_klass##nv_suffix(klass);                                          \
          }                                                                               \
        }                                                                                 \
      }                                                                                   \
                                                                                          \
      //遍历mr范围内的静态oop                                                                                    
      if (UseCompressedOops) {                                                            \
        InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr);    \
      } else {                                                                            \
        InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr);          \
      }                                                                                   \
    }
     
    #define InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(T, nv_suffix, mr)         \
      InstanceMirrorKlass_BOUNDED_OOP_ITERATE(                                            \
        start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj),        \
        mr.start(), mr.end(),                                                             \
          (closure)->do_oop##nv_suffix(p),                                                \
        assert_is_in_closed_subset)                                                       \
      return oop_size(obj);                                                               \
    #define InstanceMirrorKlass_BOUNDED_OOP_ITERATE(start_p, count, low, high, \
                                              do_oop, assert_fn)               \
    {                                                                          \
      if (UseCompressedOops) {                                                 \
        InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop,         \
          start_p, count,                                                      \
          low, high,                                                           \
          do_oop, assert_fn)                                                   \
      } else {                                                                 \
        InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,               \
          start_p, count,                                                      \
          low, high,                                                           \
          do_oop, assert_fn)                                                   \
      }                                                                        \
    }
     
    //跟InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE相比就是多了一个对oop的地址范围的判断,只处理处于该范围内的oop
    #define InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE( \
      T, start_p, count, low, high,                              \
      do_oop, assert_fn)                                         \
    {                                                            \
      T* const l = (T*)(low);                                    \
      T* const h = (T*)(high);                                   \
      assert(mask_bits((intptr_t)l, sizeof(T)-1) == 0 &&         \
             mask_bits((intptr_t)h, sizeof(T)-1) == 0,           \
             "bounded region must be properly aligned");         \
      T* p       = (T*)(start_p);                                \
      T* end     = p + (count);                                  \
      if (p < l) p = l;                                          \
      if (end > h) end = h;                                      \
      while (p < end) {                                          \
        (assert_fn)(p);                                          \
        do_oop;                                                  \
        ++p;                                                     \
      }                                                          \
    }
     
     
    ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
    ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
     
    #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                          \
    int InstanceMirrorKlass::                                                             \
    oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) {              \
      /* Get size before changing pointers */                                             \
      SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);      \
                                                                                          \
      InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure);                  \
                                                                                          \
      //遍历静态oop                                                                                    
      if (UseCompressedOops) {                                                            \
        InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(narrowOop, nv_suffix);           \
      } else {                                                                            \
        InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix);                 \
      }                                                                                   \
    }
    

    相关文章

      网友评论

          本文标题:oop_iterate

          本文链接:https://www.haomeiwen.com/subject/nvhhqdtx.html