JVM源码探秘:System.gc全面解析

发布于:2024-06-01 ⋅ 阅读:(121) ⋅ 点赞:(0)
概述

Java虚拟机(JVM)的垃圾回收(GC)通常由VM自身根据预设条件触发,但开发者也可通过特定手段人为触发,比如使用System.gc()、Runtime.gc()或JMap操作等。本文将深入探讨System.gc()`的底层原理及其背后的故事。

已知知识点回顾
  • System.gc()执行的是完全GC(Full GC)。
  • 它会暂停整个Java进程。
  • 通常建议禁用-XX:+DisableExplicitGC禁用以避免其调用。
  • CMS GC模式下,通过-XX:+ExplicitGCInvokesConcurrent实现更高效的GC(比Full GC效果好)。
  • 堆外内存分配时,有时需配合System.gc()
更深层次疑问
  • 为何CMS GC下,-XX:+ExplicitGCInvokesConcurrent比Full GC表现更优?
  • 它是如何暂停整个进程的?
  • 为何堆外内存分配需要System.gc()
HotSpot VM下System.gc()的实现路径

Java层实现

public static void gc() {
    Runtime.getRuntime().gc();
}

public native void gc();

HotSpot VM层

  • 寻找Native实现:通过方法名Java_pkgName_className_methodName.替换为_)定位C源码,此处为Java_java_lang_Runtime_gc`。

核心逻辑

JNIEXPORT void JNICALL
Java_java_lang_Runtime_gc(JNIEnv *env, jobject this) {
    JVM_GC();
}

JVM_ENTRY_NO_ENV(void, JVM_GC(void))
VMWrapper("JVM_GC");
if (!DisableExplicitGC) {
    Universe::heap()->collect(GCCause::_java_lang_system_gc);
}
JVM_END

product(bool, DisableExplicitGC, false,
"Tells whether calling System.gc() does a full GC")

void GenCollectedHeap::collect(GCCause::Cause cause) {
    if (should_do_concurrent_full_gc(cause)) {
        collect_mostly_concurrent(cause);
    } else {
        // 串行回收逻辑
    }
}

bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
    return UseConcMarkSweepGC &&
           ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
           (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
}
参数解析
  • **DisableExplicitGC-XX:+DisableGC设置此标志,直接跳过GC逻辑,避免执行。
  • ExplicitGCInvokesConcurrent:CMS模式下,-XX:+ExplicitGCInvokesConcurrent启用并发GC,而非完全暂停式的Full GC,提升性能。

**堆外内存分配与System.gc():**当堆外内存分配需要更多空间时,可能需要释放堆内内存,此时调用System.gc()促进垃圾回收,以释放空间,辅助堆外分配。

综上所述,System.gc()的实现涉及Java到VM层面的深入逻辑,通过条件判断和策略调用不同回收机制,以适应特定场景需求,理解其原理有助于优化程序性能和资源管理。


网站公告

今日签到

点亮在社区的每一天
去签到