1]任何人都可以指向文档或详细解释" Ext Root Scanning"适用于G1 GC,尤其适用于JNI处理? (如果可能,请特定于Java 7)
2]额外奖励:我们期望G1 gc的openJDK代码与Hotspot有何不同?如果我们可以预期这一点相同,那么请您指出用于G1 GC ext root扫描的openJDK代码的相关部分吗?
感谢
答案 0 :(得分:3)
来自Oracle Doc:
执行垃圾收集时,G1的运行方式与CMS收集器类似。 G1执行并发全局标记阶段以确定整个堆中对象的活跃度。
外部根区域扫描是标记过程的一个阶段。
来自Java Performance Companion:
在此阶段,扫描外部(堆外)根,例如JVM的系统字典,VM数据结构,JNI线程句柄,硬件寄存器,全局变量和线程堆栈根,以查明是否有任何点进入当前暂停的收藏集(CSet)。
是的,我们可以预期openjdk和hotspot的g1代码与here所述的相同。所以我们可以通过阅读源代码来解释详细过程。
void
G1CollectedHeap::
g1_process_strong_roots(bool collecting_perm_gen,
SharedHeap::ScanningOption so,
OopClosure* scan_non_heap_roots,
OopsInHeapRegionClosure* scan_rs,
OopsInGenClosure* scan_perm,
int worker_i) {
//...
process_strong_roots(false, // no scoping; this is parallel code
collecting_perm_gen, so,
&buf_scan_non_heap_roots,
&eager_scan_code_roots,
&buf_scan_perm);
//...
}
然后在process_strong_roots
:
// Global (strong) JNI handles
if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do))
JNIHandles::oops_do(roots);
关于JNI的核心过程:它迭代JNI处理块并找出这个句柄块的oops(oop:Java的引用抽象)是否指向堆区域,这意味着是否这个JNI oop可以是gc的根。
for (JNIHandleBlock* current = current_chain; current != NULL;
current = current->_next) {
assert(current == current_chain || current->pop_frame_link() == NULL,
"only blocks first in chain should have pop frame link set");
for (int index = 0; index < current->_top; index++) {
oop* root = &(current->_handles)[index];
oop value = *root;
// traverse heap pointers only, not deleted handles or free list
// pointers
if (value != NULL && Universe::heap()->is_in_reserved(value)) {
f->do_oop(root);
}
}
// the next handle block is valid only if current block is full
if (current->_top < block_size_in_oops) {
break;
}
}
然后,这个根在数组中被记住,当数组已满时由OopClosure
处理,在这种情况下,迭代root的引用以标记活动对象。