Hotspot 垃圾回收之oop_iterate(一) 源码解析
目录
1、oopDesc::oop_iterate/ oopDesc::oop_iterate_backwards
2、Klass::oop_oop_iterate / Klass::oop_oop_iterate_backwards
3、InstanceKlass
4、OopMapBlock
5、InstanceClassLoaderKlass
6、InstanceMirrorKlass
之前的博客在讲解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中,如下:
其实现在在同目录的objArrayOop.cpp中,如下:
即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用来定义具体类型的OopClosureTypeSPECIALIZED_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方法的实现如下:
即不同的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方法,如下:
这里用于表示具体的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,则遍历该klassclosure->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,则遍历该klassclosure->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 { \//注意外层是遍历OopMapBlockwhile (map < end_map) { \//InstanceKlass_SPECIALIZED_OOP_ITERATE遍历某个Map内包含的oopInstanceKlass_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); \//遍历指定范围的oopwhile (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了,其定义如下:
其中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的地址,如下:
分别查看0x00000000d69d98a0,0x00000000d69db5f8,0x00000000d69dd070对应的oop,如下:
上从面的截图可知,子类会完整的保留父类的属性,从而方便调用父类方法时能够正确的使用父类的属性。上述对oop的属性打印是按照类声明属性的顺序来的,内存中是这样保存的么?可以通过查看属性的偏移量来判断。
在Class Browser中搜索jvmTest,可以查找到我们三个自定义类对应的Klass,如下图:
分别点击这三个类查看属性的偏移量,如下:
根据上述偏移量,我们可以得出jvmTest.B对象的内存布局,如下:
int本身占4个字节,引用类型属性本质上就是一个指针,这里因为默认开启了指针压缩,所以也是4字节。
我们再看下表示OopMapBlock在Klass中的字宽数的属性_nonstatic_oop_map_size在三个类中的取值,如下:
OopMapBlock本身就只有两个int属性,所以一个OopMapBlock实例只有8字节,即一个字宽,jvmTest.B的_nonstatic_oop_map_size属性值为3,即由3个OopMapBlock,下面通过CHSDB的mem命令来看看这3个OopMapBlock对应的内存数据。
首先执行inspect对象得到该Klass本身的大小,即sizeof的大小,如下:
vtable,itable,OopMapBlock这三个都是内嵌在Klass里面的,所谓的内嵌实际是指这块内存是紧挨着Klass自身的属性对应的内存的下面,从上一节的分析可知,OopMapBlock在itable的后面,itable在vtable的后面,而vtable是紧挨着Klass的,从上述inspect命令的输出,也可知道itable和vtable的内存大小,单位是字宽,如下:
因此OopMapBlock的起始地址就是Klass的地址加上Klass本身的大小440字节即55字宽,再加上vtable的5字宽,itable的2字宽,总共加62字宽,OopMapBlock本身占用3个字宽,因此用mem查看这65字宽的数据,如下:
最后的3个字宽如下:
每个字宽对应一个OopMapBlock,前面4字节就是count属性,这里都是2,后面4字节就是offset,分别是20,36,48,与jvmTest.B的内存结构是完全一致的。
5、InstanceClassLoaderKlass
InstanceClassLoaderKlass继承自InstanceKlass,用来表示java.lang.ClassLoader及其子类的Klass,该类没有新增其他的属性,主要是改写了引用遍历的方法的实现,增加了对ClassLoaderData的遍历,定义如下:
其实现如下:
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) { \//遍历ClassLoaderDataclosure->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) { \//遍历ClassLoaderDataclosure->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大小和引用遍历的相关方法,因为必须考虑类的静态属性。引用遍历的方法定义如下:
其实现如下:
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) { \//获取对应的KlassKlass* klass = java_lang_Class::as_Klass(obj); \if (klass != NULL) { \//遍历Klass,实际就是遍历对应的ClassLoaderDataclosure->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,即InstanceMirrorKlassreturn 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)) { \//获取对应的KlassKlass* klass = java_lang_Class::as_Klass(obj); \if (klass != NULL) { \//遍历Klassclosure->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); \} \
}
Hotspot 垃圾回收之oop_iterate(一) 源码解析相关推荐
- Hotspot 垃圾回收之oop_iterate(二) 源码解析
目录 1.java.lang.Class 1.1.Class实例中oop_size.klass等属性是哪来的? 1.2._offset_of_static_fields 1.3 为什么从_offset ...
- Hotspot 对象引用Reference和Finalizer 源码解析
目录 一.Reference 1.SoftReference / WeakReference / PhantomReference 2.定义 3.ReferenceHandler 4.Cleaner ...
- Hotspot 垃圾回收之GenCollectedHeap 源码解析
目录 1.定义 2.构造方法 / initialize / post_initialize 3.do_collection 4.do_full_collection 5.collect 6.VM_Ge ...
- Hotspot 垃圾回收之ReferenceProcessor(二) 源码解析
目录 1.process_discovered_reflist 2.process_phaseJNI 3.process_discovered_references 4.preclean_discov ...
- Hotspot 垃圾回收之VM_Operation 源码解析
目录 一.VM_Operation 二.VMThread 1.定义 2.create / destroy 3.run / wait_for_vm_thread_exit 4.loop 5.VMThr ...
- 小程序源码:登录已修复零象垃圾废品回收微信小程序源码下载,V2.8.2完整全开源前端+后端
零象垃圾废品回收小程序源码,V2.8.2完整全开源安装包+小程序前端, 是一款专注于垃圾回收小程序源码,支持协议定期企业废品回收,垃圾分类小区物业定期回收. 关于程序 运行环境:微擎+PHP+MYSQ ...
- Hotspot 重量级锁ObjectMonitor(一) 源码解析
目录 1.定义 2.TrySpin_VaryDuration 3.ObjectWaiter 4.EnterI 5.JavaThreadBlockedOnMonitorEnterState / OSTh ...
- Hotspot 重量级锁ObjectMonitor(二) 源码解析
目录 1.AddWaiter / DequeueWaiter /DequeueSpecificWaiter 2.wait 3.notify 4.notifyAll 5.exit 6.try_enter ...
- JAVA计算机毕业设计二手手机回收平台系统Mybatis+源码+数据库+lw文档+系统+调试部署
JAVA计算机毕业设计二手手机回收平台系统Mybatis+源码+数据库+lw文档+系统+调试部署 JAVA计算机毕业设计二手手机回收平台系统Mybatis+源码+数据库+lw文档+系统+调试部署 本源 ...
最新文章
- 再谈应用环境下的TIME_WAIT和CLOSE_WAIT
- matlab ac电源,基于MATLAB对AC/DC/AC电源的死区效应的谐波分析及仿真
- charles都踩过哪些坑_开水果店的你,踩过了哪些坑?
- 360 屏蔽ajax,怎么在easy ui做全局Ajax拦截啊?
- php员工积分绩效,详解绩效积分奖励制
- matlab 转换图片格式,Matlab实现图片格式转换 pgm转jpg等
- data 的数据代理
- php--- 转换编码
- 如何写出一个较好的快速排序程序
- java连接设备连接给参数_如何通过蓝牙连接两个设备按参数发送配对代码? JAVA,Android的...
- 什么是数据库的三大范式?
- MATLAB模式识别基本操作函数解析
- ArcView GIS 应用与开发技术(11)-空间分析
- integnps 数控智能编程v19.3 数控切割机编程 切割机套料编程
- ps的基础知识与教程
- 计算机主机mac地址怎么查,怎么查看电脑的Mac地址
- baigoStudio baigoSSO v3.0.1(Use CVE-2019-10015.)
- CDR教程-使用调和工具制作三八天猫标志
- 三大运营商的网上流量卡数据对比,看看你会选哪一个?
- 微PE工具箱增加安装Linux/Ubuntu/Centos/deepin系统菜单
热门文章
- 温度计:不用水银,或者不用易碎玻璃,难道就不行?
- LeetCode 461. 汉明距离
- c语言100w数据排序需要多久,验证:如何快速插入100w数据
- linux密码忘了?一招解决
- 科研试剂5,10,15,20-四(4-羟基苯)-21H,23H-卟啉(51094-17-8);铕配合物Eu-pyP;5-对-(对羰基苯甲酸)-氨基苯基-10,1 5,20-三苯基卟啉铜Cu(p-CP
- 启用Microsoft loopback Adapte
- 最新微信漏洞曝光:利用微信群邮件日吸过万精准流量
- C++ TGP 模板基础知识--01函数模板
- 22第十一章:【01】进程管理
- java抓取并保存图片_利用JAVA抓取网站的所有图片并保存于本地