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方法,如下:
这里用于表示具体的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了,其定义如下:
其中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.pngint本身占4个字节,引用类型属性本质上就是一个指针,这里因为默认开启了指针压缩,所以也是4字节。
我们再看下表示OopMapBlock在Klass中的字宽数的属性_nonstatic_oop_map_size在三个类中的取值,如下:
image.png image.png image.pngOopMapBlock本身就只有两个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的遍历,定义如下:
其实现如下:
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); \
} \
}
网友评论