Java 为什么JNI活动实例会阻止GC? bool PSScavenge::invoke_no_policy()

Java 为什么JNI活动实例会阻止GC? bool PSScavenge::invoke_no_policy(),java,garbage-collection,jvm,jvm-hotspot,Java,Garbage Collection,Jvm,Jvm Hotspot,如您所见,如果GCLocker::check\u active\u before\u gc()为true,则它不会调用次要gc,即PSScavenge::invoke\u no\u policy()。为什么 检查\u gc()之前的\u活动\u _是否处于活动状态() 是否处于活动状态\u内部() _jni\u锁\u计数 \u jni\u lock\u count跟踪正在运行的线程数 目前在一个关键地区 \u jni\u lock\u count跟踪当前处于关键区域的线程数 如前所述,JNI关键

如您所见,如果
GCLocker::check\u active\u before\u gc()
true
,则它不会调用次要gc,即
PSScavenge::invoke\u no\u policy()
。为什么

检查\u gc()之前的\u活动\u _是否处于活动状态() 是否处于活动状态\u内部() _jni\u锁\u计数
\u jni\u lock\u count
跟踪正在运行的线程数
目前在一个关键地区

\u jni\u lock\u count
跟踪当前处于关键区域的线程数

如前所述,JNI关键函数暂时禁用垃圾收集

调用GetPrimitiveArrayCritical后,本机代码不应 在调用之前运行一段较长的时间 ReleasePrimitiveArrayCritical。我们必须处理这一对中的代码 在“关键区域”中运行的函数。在关键区域中运行 区域,本机代码不得调用其他JNI函数或任何系统 可能导致当前线程阻塞并等待另一个线程的调用 Java线程。(例如,当前线程不能在 流正在由另一个Java线程写入。)

这些限制使本机代码更有可能 获取阵列的未复制版本,即使VM没有 支持钉扎。例如,VM可能会暂时禁用垃圾 当本机代码持有指向数组的指针时 通过GetPrimitiveArrayCritical获取

  ...
  if (GCLocker::check_active_before_gc()) {
    return false;
  }
  ...
bool GCLocker::check_active_before_gc() {
  assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
  if (is_active() && !_needs_gc) {
    verify_critical_count();
    _needs_gc = true;
    log_debug_jni("Setting _needs_gc.");
  }
  return is_active();
}
  // Accessors
  static bool is_active() {
    assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
    return is_active_internal();
  }
  static bool is_active_internal() {
    verify_critical_count();
    return _jni_lock_count > 0;
  }
static volatile jint _jni_lock_count;  // number of jni active instances.