Docs/code/detailed G1 gc 上 "Ext Root Scanning" 的解释?
Docs/code/detailed explanation for "Ext Root Scanning" on G1 gc?
1] 谁能指出文档或详细解释 "Ext Root Scanning" 如何在 G1 GC 中工作,尤其是对于 JNI 句柄? (请具体到Java7)
2] 奖励:我们期望 G1 gc 的 openJDK 代码与 Hotspot 有何不同?如果我们可以预期这是相同的,请您指出用于 G1 GC ext root 扫描的 openJDK 代码的相关部分吗?
谢谢
概览
来自Oracle Doc:
When performing garbage collections, G1 operates in a manner similar to the CMS collector. G1 performs a concurrent global marking phase to determine the liveness of objects throughout the heap.
外部根区域扫描是标记过程的阶段之一。
来自 Java 性能伴侣:
During this phase the external (off-heap) roots such as the JVM’s system dictionary, VM data structures, JNI thread handles, hardware registers, global variables, and thread stack roots are scanned to find out if any point into the current pause’s collection set (CSet).
详细信息和代码
是的,我们可以预期 openjdk 和热点的 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
处理,在这种情况下,迭代根的引用以标记活对象。
更多:
1] 谁能指出文档或详细解释 "Ext Root Scanning" 如何在 G1 GC 中工作,尤其是对于 JNI 句柄? (请具体到Java7)
2] 奖励:我们期望 G1 gc 的 openJDK 代码与 Hotspot 有何不同?如果我们可以预期这是相同的,请您指出用于 G1 GC ext root 扫描的 openJDK 代码的相关部分吗?
谢谢
概览
来自Oracle Doc:
When performing garbage collections, G1 operates in a manner similar to the CMS collector. G1 performs a concurrent global marking phase to determine the liveness of objects throughout the heap.
外部根区域扫描是标记过程的阶段之一。
来自 Java 性能伴侣:
During this phase the external (off-heap) roots such as the JVM’s system dictionary, VM data structures, JNI thread handles, hardware registers, global variables, and thread stack roots are scanned to find out if any point into the current pause’s collection set (CSet).
详细信息和代码
是的,我们可以预期 openjdk 和热点的 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
处理,在这种情况下,迭代根的引用以标记活对象。