1、java.lang.Class
理解InstanceMirrorKlass的引用遍历逻辑,我们需要逐步弄清楚以下几个问题:
1.1、Class实例中oop_size、klass等属性是哪来的?
查看java.lang.Class的源码可知,该类并没有oop_size、klass等属性的声明,但是通过HSDB查看该类的Klass确实有该属性,测试用例如下:
package jvmTest;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
class Base{
public static int a=1;
public static String s="abc";
public static Integer a2=6;
public static Integer a3=8;
public static int a4=4;
private int a5=12;
private Integer a6=13;
private int a7=13;
}
public class MainTest {
public static void main(String[] args) {
Class a=Base.class;
System.out.println(Base.a);
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();
}
}
在Class Browser中搜索java.lang.Class,第一个便是该类对应的Klass,如下图:
image.png点击该类可以发现该类其实是有很多属性的,如下:
image.png
上述private开头的属性在源码中都可以找到,就是比较分散隐蔽,从klass开始的剩余几个属性在源码中都没有,那这些属性是谁加进去的,什么时候加进去的了?答案是JVM,JVM在解析class文件中包含的属性时判断是java.lang.Class就会注入一部分字段放到属性的解析结果Array<u2>中,关键代码在负责字段解析的ClassFileParser::parse_fields方法中,如下图:
image.png其中JavaClasses::get_injected就是返回需要注入的字段数组,其实现如下:
InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) {
*field_count = 0;
vmSymbols::SID sid = vmSymbols::find_sid(class_name);
if (sid == vmSymbols::NO_SID) {
// Only well known classes can inject fields
return NULL;
}
int count = 0;
int start = -1;
#define LOOKUP_INJECTED_FIELD(klass, name, signature, may_be_java) \
if (sid == vmSymbols::VM_SYMBOL_ENUM_NAME(klass)) { \
//如果klass一致则增加count
count++; \
//如果start未初始化,则初始化,表示数组的起始位置
if (start == -1) start = klass##_##name##_enum; \
}
ALL_INJECTED_FIELDS(LOOKUP_INJECTED_FIELD);
#undef LOOKUP_INJECTED_FIELD
if (start != -1) {
//如果找到了,将field_count置为count
*field_count = count;
//返回_injected_fields数组中start处开始的元素,元素个数就是count
return _injected_fields + start;
}
return NULL;
}
#define ALL_INJECTED_FIELDS(macro) \
CLASS_INJECTED_FIELDS(macro) \
CLASSLOADER_INJECTED_FIELDS(macro) \
MEMBERNAME_INJECTED_FIELDS(macro)
//java.lang.Class中新增的属性
#define CLASS_INJECTED_FIELDS(macro) \
macro(java_lang_Class, klass, intptr_signature, false) \
macro(java_lang_Class, array_klass, intptr_signature, false) \
macro(java_lang_Class, oop_size, int_signature, false) \
macro(java_lang_Class, static_oop_field_count, int_signature, false) \
macro(java_lang_Class, protection_domain, object_signature, false) \
macro(java_lang_Class, init_lock, object_signature, false) \
macro(java_lang_Class, signers, object_signature, false)
//_injected_fields是一个InjectedField数组
InjectedField JavaClasses::_injected_fields[] = {
ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD)
};
#define DECLARE_INJECTED_FIELD(klass, name, signature, may_be_java) \
{ SystemDictionary::WK_KLASS_ENUM_NAME(klass), vmSymbols::VM_SYMBOL_ENUM_NAME(name##_name), vmSymbols::VM_SYMBOL_ENUM_NAME(signature), may_be_java },
从源码分析可知,处java.lang.Class外还有一些类也会以同样的方式注入新的属性,如下:
#define CLASSLOADER_INJECTED_FIELDS(macro) \
macro(java_lang_ClassLoader, loader_data, intptr_signature, false)
#define MEMBERNAME_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MemberName, vmloader, object_signature, false) \
macro(java_lang_invoke_MemberName, vmindex, intptr_signature, false) \
macro(java_lang_invoke_MemberName, vmtarget, intptr_signature, false)
1.2、_offset_of_static_fields
InstanceMirrorKlass就增加了一个静态属性_offset_of_static_fields,用来描述静态字段的起始偏移量,因为是静态的,无法在HSDB中直接查看该属性。该属性是通过init_offset_of_static_fields方法初始化的,其实现如下:
static void init_offset_of_static_fields() {
//_offset_of_static_fields是静态字段,未初始化时系统自动赋值0
assert(_offset_of_static_fields == 0, "once");
//SystemDictionary::Class_klass()就是全局唯一的InstanceMirrorKlass实例
_offset_of_static_fields = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->size_helper() << LogHeapWordSize;
}
int size_helper() const {
return layout_helper_to_size_helper(layout_helper());
}
static int layout_helper_to_size_helper(jint lh) {
assert(lh > (jint)_lh_neutral_value, "must be instance");
return lh >> LogHeapWordSize;
}
int layout_helper() const { return _layout_helper; }
InstanceMirrorKlass的_layout_helper的取值是105,如下:
image.png
因此_offset_of_static_fields的值就是104。从上一节的Class包含的字段属性来看,该类的实例按照对象头和属性算出来的大小应该是100,但是必须按照一个字段对应的字节数即8对齐,因此是104,_layout_helper的值是为了保证通过size_helper方法计算的实例大小能够不低于实际的大小。
该方法的调用链如下:
image.png
1.3 为什么从_offset_of_static_fields处开始遍历?
_offset_of_static_fields描述的是静态字段的起始偏移量,并非静态引用类型字段的起始偏移量,为什么要从这个偏移处开始遍历了?答案是Class实例为了确保通用性,将静态的引用类型属性都放在了一起且是静态字段区域的起始位置,然后通过static_oop_field_count属性就可以准确的定位所包含的oop了,这个跟普通类的实例完全相反,普通类实例的引用类型属性都是放在实例内存区域的最后,下面以上述的测试用例来说明。
先在Stack Memory中找到变量a即Base.class的地址,如下图:
image.png然后在CHSDB中查看该地址对应的对象,如下:
image.png
该实例的大小是128,这个大小不是通过sizeof得出来的,而是从该oop的oop_size属性中读取出来的,用mem查看接下来的128字节即16个字段的内存数据,如下:
image.png因为intel存储数据时是按照小端存储的,所以最后4行的真实内存数据应该如下:
0x00000000d69d9d78: 0x00000003 00000000
0x00000000d69d9d80: 0xd69d9dc0 d687bde0
0x00000000d69d9d88: 0xd687be00 00000001
0x00000000d69d9d90: 0x00000004 00000000
倒数第四行就是偏移量为96的起始位置,0x00000003就是字段static_oop_field_count的值了,即当前oop包含的静态oop属性的个数为3。倒数第三行就是偏移量为104的起始位置,即从此处开始就是保存的静态字段了。0xd69d9dc0就是属性s的压缩指针,d687bde0就是属性a2的压缩指针,0xd687be00就是属性a3的压缩指针了,剩下的两个00000001和0x00000004就是属性a和a4了。
2、InstanceRefKlass
InstanceRefKlass继承自InstanceKlass,用来表示java/lang/ref/Reference及其子类的Klass,该类没有新增属性,主要改写了用于调整对象指针的oop_adjust_pointers方法和引用遍历的方法,其中引用遍历的方法定义如下:
其实现如下:
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
\
int InstanceRefKlass:: \
oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
/* Get size before changing pointers */ \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
\
//遍历Reference实例自身的属性,实际只遍历其中的queue属性,其他属性都在下面的宏方法中遍历
int size = InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \
\
if (UseCompressedOops) { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains); \
} else { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \
} \
}
//contains是一个模板方法,默认返回true
template <class T> bool contains(T *t) { return true; }
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
\
int InstanceRefKlass:: \
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 (UseCompressedOops) { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr.contains); \
} else { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr.contains); \
} \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#if INCLUDE_ALL_GCS
#define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
\
int InstanceRefKlass:: \
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); \
\
if (UseCompressedOops) { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains); \
} else { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \
} \
}
#endif // INCLUDE_ALL_GCS
上述三类方法的实现除调用父类InstanceKlass的对应方法外,最终都落脚到对宏InstanceRefKlass_SPECIALIZED_OOP_ITERATE的调用,其实现如下:
#define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains) \
//获取该实例的discovered属性地址
T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \
if (closure->apply_to_weak_ref_discovered_field()) { \
//如果需要遍历discovered属性
closure->do_oop##nv_suffix(disc_addr); \
} \
\
//获取该实例的referent属性地址
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \
//读取对应的oop
T heap_oop = oopDesc::load_heap_oop(referent_addr); \
//获取ReferenceProcessor引用
ReferenceProcessor* rp = closure->_ref_processor; \
if (!oopDesc::is_null(heap_oop)) { \
//如果heap_oop非空,则将其解密成真实地址的oop
oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); \
//如果referent的对象头没有GC打标,只有堆内存压缩的时候才会打标
if (!referent->is_gc_marked() && (rp != NULL) && \
//将其加入到对应类型的DiscoveredList中,等待处理
rp->discover_reference(obj, reference_type())) { \
return size; \
} else if (contains(referent_addr)) { \
//如果已经GC打标了,说明还有其他对象引用该oop,则将其视为根节点正常遍历
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
closure->do_oop##nv_suffix(referent_addr); \
} \
} \
//获取该实例的next属性的地址
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \
//JDK8下为true,表示使用discovered字段来构成pending_list
if (ReferenceProcessor::pending_list_uses_discovered_field()) { \
//获取next属性对应的oop
T next_oop = oopDesc::load_heap_oop(next_addr); \
/* Treat discovered as normal oop, if ref is not "active" (next non-NULL) */\
if (!oopDesc::is_null(next_oop) && contains(disc_addr)) { \
//next属性非空,说明该实例已经被加入到ReferenceQueue中,此时discovered属性通常为null
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
closure->do_oop##nv_suffix(disc_addr); \
} \
} \
/* treat next as normal oop */ \
if (contains(next_addr)) { \
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \
//遍历next属性
closure->do_oop##nv_suffix(next_addr); \
} \
return size; \
//父类的方法
ReferenceType reference_type() const { return (ReferenceType)_reference_type; }
//_pending_list_uses_discovered_field默认为false,表示是否使用discovered字段来构成pending_list
//是从JDK_Version信息中获取的,JDK8下为true
static bool pending_list_uses_discovered_field() {
return _pending_list_uses_discovered_field;
}
Reference的相关属性的用途可以参考Hotspot 对象引用Reference和Finalizer 。理解上述逻辑的一个关键是,referent属性会不会作为Reference的引用类型属性在第一步的InstanceKlass::oop_oop_iterate方法中被遍历到,答案是不会,我们可以通过HSDB来查看Reference的OopMapBlock,先在Class Browser中搜索java.lang.ref.Reference,搜索结果的第一个就是我们期望的InstanceRefKlass了,其包含的属性及其偏移量如下:
image.png
总共6个属性,最后两个是静态属性,不会出现在Reference实例对应的oop中,接着在CHSDB中,用inspect命令查看该Klass,如下:
image.png
从输出中可以知道该类的大小是440字节即55字宽,vtable是9个字宽,itable是2个字宽,且OopMapBlock的字宽数为1,所以OopMapBlock对应的内存就是第67个字宽,执行mem 0x0000000016a95d28 67命令,最后一行的内存数据如下:
image.png其中前4个字节就是OopMapBlock的count属性,值为1,后面的4个字节就是OopMapBlock的offset属性,置为16,即第一步的InstanceKlass::oop_oop_iterate方法只会遍历queue这一个属性,referent属性,next属性和discovered属性都是在InstanceRefKlass_SPECIALIZED_OOP_ITERATE中处理的。
3、ObjArrayKlass
ObjArrayKlass继承自表示数组的ArrayKlass,用来表示对象数组或者二维数组的Klass,该Klass对应的oopDesc就是objArrayOopDesc。ArrayKlass中没有新增引用遍历的相关方法,只有ObjArrayKlass中有,其定义如下:
注意这里只改写了三类方法的定义,还有一类oop_oop_iterate_backwards方法,该方法使用Klass的默认实现,最终调用oop_oop_iterate方法完成遍历,ObjArrayKlass中该方法的实现如下:
image.pngoop_oop_iterate_v就是上面改写的三类方法中的其中一个。 这三类方法实现如下:
ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
\
int ObjArrayKlass::oop_oop_iterate##nv_suffix(oop obj, \
OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
//校验该实例是数组类型
assert (obj->is_array(), "obj must be array"); \
objArrayOop a = objArrayOop(obj); \
//获取该数组实例的整体大小
int size = a->object_size(); \
if_do_metadata_checked(closure, nv_suffix) { \
//遍历该对象数组的对象类型klass
closure->do_klass##nv_suffix(obj->klass()); \
} \
//遍历数组元素
ObjArrayKlass_OOP_ITERATE(a, p, (closure)->do_oop##nv_suffix(p)) \
return size; \
}
int object_size() { return object_size(length()); }
static int object_size(int length) {
//获取数组元素部分的大小,单位是字宽
uint asz = array_size(length);
//再加上对象头的大小,计算完整的数组的大小
uint osz = align_object_size(header_size() + asz);
assert(osz >= asz, "no overflow");
assert((int)osz > 0, "no overflow");
return (int)osz;
}
static int array_size(int length) {
//heapOopSize表示堆内存中oop的大小,开启指针压缩下是4字节,不开启是8字节
//HeapWordSize表示一个字宽的字节数,64位下是8
const uint OopsPerHeapWord = HeapWordSize/heapOopSize;
assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0),
"Else the following (new) computation would be in error");
uint res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord;
return res;
}
#define ObjArrayKlass_OOP_ITERATE(a, p, do_oop) \
if (UseCompressedOops) { \
ObjArrayKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
a, p, do_oop) \
} else { \
ObjArrayKlass_SPECIALIZED_OOP_ITERATE(oop, \
a, p, do_oop) \
}
#define ObjArrayKlass_SPECIALIZED_OOP_ITERATE(T, a, p, do_oop) \
{ \
T* p = (T*)(a)->base(); \
T* const end = p + (a)->length(); \
//根据数组长度计算终止地址,遍历指定范围内的oop
while (p < end) { \
do_oop; \
p++; \
} \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
\
int ObjArrayKlass::oop_oop_iterate##nv_suffix##_m(oop obj, \
OopClosureType* closure, \
MemRegion mr) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
assert(obj->is_array(), "obj must be array"); \
objArrayOop a = objArrayOop(obj); \
int size = a->object_size(); \
if_do_metadata_checked(closure, nv_suffix) { \
closure->do_klass##nv_suffix(a->klass()); \
} \
ObjArrayKlass_BOUNDED_OOP_ITERATE( \
a, p, mr.start(), mr.end(), (closure)->do_oop##nv_suffix(p)) \
return size; \
}
#define ObjArrayKlass_BOUNDED_OOP_ITERATE(a, p, low, high, do_oop) \
if (UseCompressedOops) { \
ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
a, p, low, high, do_oop) \
} else { \
ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
a, p, low, high, do_oop) \
}
#define ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(T, a, p, low, high, do_oop) \
{ \
T* const l = (T*)(low); \
T* const h = (T*)(high); \
T* p = (T*)(a)->base(); \
T* end = p + (a)->length(); \
//遍历所有的在指定范围中的数组元素
if (p < l) p = l; \
if (end > h) end = h; \
while (p < end) { \
do_oop; \
++p; \
} \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r(OopClosureType, nv_suffix) \
\
//start和end是指遍历的数组元素的起止索引
int ObjArrayKlass::oop_oop_iterate_range##nv_suffix(oop obj, \
OopClosureType* closure, \
int start, int end) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
assert(obj->is_array(), "obj must be array"); \
objArrayOop a = objArrayOop(obj); \
//获取该数组的大小
int size = a->object_size(); \
if (UseCompressedOops) { \
//获取start处元素的地址
HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<narrowOop>(start);\
//获取end处元素的地址
HeapWord* high = (HeapWord*)((narrowOop*)a->base() + end); \
MemRegion mr(low, high); \
if_do_metadata_checked(closure, nv_suffix) { \
closure->do_klass##nv_suffix(a->klass()); \
} \
//遍历指定范围内的数组元素
ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
a, p, low, high, (closure)->do_oop##nv_suffix(p)) \
} else { \
HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<oop>(start); \
HeapWord* high = (HeapWord*)((oop*)a->base() + end); \
MemRegion mr(low, high); \
if_do_metadata_checked(closure, nv_suffix) { \
/* SSS: Do we need to pass down mr here? */ \
closure->do_klass##nv_suffix(a->klass()); \
} \
ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
a, p, low, high, (closure)->do_oop##nv_suffix(p)) \
} \
return size; \
}
其实现整体上跟InstanceKlass一致,就是获取遍历的地址范围时由从OopMapBlock获取改成了从自身的数组基地址和元素个数获取。
4、oopDesc::adjust_pointers / follow_contents
adjust_pointers用于调整引用类型属性使其指向新的对象地址,这个新的对象地址可能是对象promote产生的,也可能是堆空间压缩产生的;第二个方法是专为负责堆空间压缩的MarkSweep准备的,同样是用来遍历各引用类型属性。这两方法对引用类型属性的遍历逻辑和oopDesc::oop_iterate类方法基本一致,其实现如下:
其调用链如下:
image.png image.pngKlass定义了这两方法,但是没有给出默认实现,现在来逐一探讨Klass各子类的实现。
4.1、InstanceKlass
int InstanceKlass::oop_adjust_pointers(oop obj) {
int size = size_helper();
InstanceKlass_OOP_MAP_ITERATE( \
obj, \
MarkSweep::adjust_pointer(p), \
assert_is_in)
return size;
}
//使用同样的遍历逻辑
#define InstanceKlass_OOP_MAP_ITERATE(obj, do_oop, assert_fn) \
{ \
/* Compute oopmap block range. The common case \
is nonstatic_oop_map_size == 1. */ \
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 { \
while (map < end_map) { \
InstanceKlass_SPECIALIZED_OOP_ITERATE(oop, \
obj->obj_field_addr<oop>(map->offset()), map->count(), \
do_oop, assert_fn) \
++map; \
} \
} \
}
template <class T> inline void MarkSweep::adjust_pointer(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
//获取p原来指向的对象obj,然后从对象头中获取新的对象地址new_obj
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
oop new_obj = oop(obj->mark()->decode_pointer());
assert(new_obj != NULL || // is forwarding ptr?
obj->mark() == markOopDesc::prototype() || // not gc marked?
(UseBiasedLocking && obj->mark()->has_bias_pattern()),
// not gc marked?
"should be forwarded");
if (new_obj != NULL) {
//new_obj不为空,则修改p,让其指向新地址
assert(Universe::heap()->is_in_reserved(new_obj),
"should be in object space");
oopDesc::encode_store_heap_oop_not_null(p, new_obj);
}
}
}
void InstanceKlass::oop_follow_contents(oop obj) {
assert(obj != NULL, "can't follow the content of NULL object");
MarkSweep::follow_klass(obj->klass());
InstanceKlass_OOP_MAP_ITERATE( \
obj, \
MarkSweep::mark_and_push(p), \ //如果p没有在对象头中打标,则打标,如果对象头中包含有非初始化的信息,则保存对象头
assert_is_in_closed_subset)
}
4.2、InstanceClassLoaderKlass
InstanceClassLoaderKlass继承自InstanceKlass,只改写了oop_follow_contents方法的实现了该ClassLoader实例对应的ClassLoaderData的遍历,如下:
4.3、InstanceMirrorKlass
InstanceMirrorKlass继承自InstanceKlass,两个方法都改写了,增加了对静态字段的遍历处理,其实现如下:
int InstanceMirrorKlass::oop_adjust_pointers(oop obj) {
int size = oop_size(obj);
InstanceKlass::oop_adjust_pointers(obj);
//遍历oop包含的静态oop字段
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
MarkSweep::adjust_pointer(p), \
assert_nothing)
return size;
}
void InstanceMirrorKlass::oop_follow_contents(oop obj) {
InstanceKlass::oop_follow_contents(obj);
//获取该Class实例对应的类Klass
Klass* klass = java_lang_Class::as_Klass(obj);
if (klass != NULL) {
if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
//如果是匿名类则使用follow_class_loader方法,因为匿名类没有对应的ClassLoader
MarkSweep::follow_class_loader(klass->class_loader_data());
} else {
//底层还是遍历该Klass对应的ClassLoader实例
MarkSweep::follow_klass(klass);
}
} else {
//如果klass为空则是基本类型对应的class
assert(java_lang_Class::is_primitive(obj), "Sanity check");
}
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
MarkSweep::mark_and_push(p), \
assert_is_in_closed_subset)
}
#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) \
} \
}
4.4、InstanceRefKlass
InstanceRefKlass继承自InstanceKlass,两个方法都改写了,增加了referent属性,next属性和discovered属性的处理。
int InstanceRefKlass::oop_adjust_pointers(oop obj) {
int size = size_helper();
//对Reference类实例而言,该方法只处理queue一个属性
InstanceKlass::oop_adjust_pointers(obj);
//处理另外三个属性,即使可能为空
if (UseCompressedOops) {
specialized_oop_adjust_pointers<narrowOop>(this, obj);
} else {
specialized_oop_adjust_pointers<oop>(this, obj);
}
return size;
}
template <class T> void specialized_oop_adjust_pointers(InstanceRefKlass *ref, oop obj) {
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
//处理referent属性
MarkSweep::adjust_pointer(referent_addr);
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
//处理next属性
MarkSweep::adjust_pointer(next_addr);
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
//处理discovered属性
MarkSweep::adjust_pointer(discovered_addr);
}
void InstanceRefKlass::oop_follow_contents(oop obj) {
if (UseCompressedOops) {
specialized_oop_follow_contents<narrowOop>(this, obj);
} else {
specialized_oop_follow_contents<oop>(this, obj);
}
}
template <class T>
void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
//获取referent属性对应的对象
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
T heap_oop = oopDesc::load_heap_oop(referent_addr);
if (!oopDesc::is_null(heap_oop)) {
//heap_oop解密
oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
if (!referent->is_gc_marked() &&
MarkSweep::ref_processor()->discover_reference(obj, ref->reference_type())) {
// 如果referent对象未打标,且成功将其加入到对应类型的DiscoverList中,调用父类的oop_follow_contents方法处理该Reference实例
ref->InstanceKlass::oop_follow_contents(obj);
return;
} else {
//如果已打标或者加入DiscoverList失败,则将referent对象作为普通的对象处理
MarkSweep::mark_and_push(referent_addr);
}
}
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
//如果使用discovered属性来构成pending_list
if (ReferenceProcessor::pending_list_uses_discovered_field()) {
T next_oop = oopDesc::load_heap_oop(next_addr);
if (!oopDesc::is_null(next_oop)) {
//如果next属性非空,则该Reference实例不是Active状态,处理其discovered属性
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
MarkSweep::mark_and_push(discovered_addr);
}
} else {
}
//处理next属性
MarkSweep::mark_and_push(next_addr);
ref->InstanceKlass::oop_follow_contents(obj);
}
4.6、TypeArrayKlass
TypeArrayKlass实现了这两方法,不过是空实现,因为其没有包含任何oop,如下:
void TypeArrayKlass::oop_follow_contents(oop obj) {
assert(obj->is_typeArray(),"must be a type array");
}
int TypeArrayKlass::oop_adjust_pointers(oop obj) {
assert(obj->is_typeArray(),"must be a type array");
typeArrayOop t = typeArrayOop(obj);
return t->object_size();
}
4.7、ObjArrayKlass
ObjArrayKlass实现了这两方法,增加了对数组元素oop的处理,如下:
int ObjArrayKlass::oop_adjust_pointers(oop obj) {
assert(obj->is_objArray(), "obj must be obj array");
objArrayOop a = objArrayOop(obj);
//获取数组大小
int size = a->object_size();
ObjArrayKlass_OOP_ITERATE(a, p, MarkSweep::adjust_pointer(p))
return size;
}
void ObjArrayKlass::oop_follow_contents(oop obj) {
assert (obj->is_array(), "obj must be array");
MarkSweep::follow_klass(obj->klass());
if (UseCompressedOops) {
objarray_follow_contents<narrowOop>(obj, 0);
} else {
objarray_follow_contents<oop>(obj, 0);
}
}
template <class T>
void ObjArrayKlass::objarray_follow_contents(oop obj, int index) {
objArrayOop a = objArrayOop(obj);
const size_t len = size_t(a->length());
const size_t beg_index = size_t(index);
assert(beg_index < len || len == 0, "index too large");
//ObjArrayMarkingStride的默认值是512,一次push的oop的数量不能超过该值
const size_t stride = MIN2(len - beg_index, ObjArrayMarkingStride);
const size_t end_index = beg_index + stride;
T* const base = (T*)a->base();
T* const beg = base + beg_index;
T* const end = base + end_index;
//将指定返回的oop push
for (T* e = beg; e < end; e++) {
MarkSweep::mark_and_push<T>(e);
}
if (end_index < len) {
//还有未处理完的,则作为一个ObjArrayTask,后面继续push
MarkSweep::push_objarray(a, end_index); // Push the continuation.
}
}
网友评论