" Ext Root Scanning"的文档/代码/详细解释在G1 gc上?

时间:2017-04-25 16:16:36

标签: java garbage-collection g1gc

1]任何人都可以指向文档或详细解释" Ext Root Scanning"适用于G1 GC,尤其适用于JNI处理? (如果可能,请特定于Java 7)

2]额外奖励:我们期望G1 gc的openJDK代码与Hotspot有何不同?如果我们可以预期这一点相同,那么请您指出用于G1 GC ext root扫描的openJDK代码的相关部分吗?

感谢

1 个答案:

答案 0 :(得分:3)

概述

来自Oracle Doc

  

执行垃圾收集时,G1的运行方式与CMS收集器类似。 G1执行并发全局标记阶段以确定整个堆中对象的活跃度。

外部根区域扫描是标记过程的一个阶段。

来自Java Performance Companion:

  

在此阶段,扫描外部(堆外)根,例如JVM的系统字典,VM数据结构,JNI线程句柄,硬件寄存器,全局变量和线程堆栈根,以查明是否有任何点进入当前暂停的收藏集(CSet)。

详细信息和代码

是的,我们可以预期openjdk和hotspot的g1代码与here所述的相同。所以我们可以通过阅读源代码来解释详细过程。

来自G1CollectedHeap

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的引用以标记活动对象。

更多: