为什么JNI活动实例会阻止GC?

时间:2017-12-15 16:41:23

标签: java garbage-collection jvm jvm-hotspot

bool PSScavenge :: invoke_no_policy()

  ...
  if (GCLocker::check_active_before_gc()) {
    return false;
  }
  ...

如您所见,如果GCLocker::check_active_before_gc()true,则不会调用次要GC,即PSScavenge::invoke_no_policy()。为什么?

check_active_before_gc()

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();
}

IS_ACTIVE()

  // Accessors
  static bool is_active() {
    assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
    return is_active_internal();
  }

is_active_internal()

  static bool is_active_internal() {
    verify_critical_count();
    return _jni_lock_count > 0;
  }

_jni_lock_count

static volatile jint _jni_lock_count;  // number of jni active instances.

_jni_lock_count跟踪线程数 目前处于关键地区。

1 个答案:

答案 0 :(得分:5)

_jni_lock_count会跟踪当前位于关键区域的线程数。

作为suggested by JNI specification,JNI关键功能暂时禁用垃圾收集。

  

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

     

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