规避代码级别的System.gc调用
源起:
System.gc()的调用, 会使用Full GC的方式回收整个堆而会忽略CMS或G1等相关回收器,Full GC可能导致长时间的STW,这个对于响应要求比较高的系统影响是致命的,有很多操作可以尽量减少Full GC频次及Full GC的操作时间,今天要涉及的是如何规避代码中直接调用System.gc导致的Full GC.
方法:
-XX:+DisableExplicitGC 禁止程序中调用System.gc(), 加了此参数, 程序若有调用, 返回的空函数调用。
该参数是如何起作用的?
下面来走一个System.gc的实现流程:
Step01:
java.lang.System.gc();
Step02:
java.lang.System
/**
* Runs the garbage collector.
* <p>
* Calling the <code>gc</code> method suggests that the Java Virtual
* Machine expend effort toward recycling unused objects in order to
* make the memory they currently occupy available for quick reuse.
* When control returns from the method call, the Java Virtual
* Machine has made a best effort to reclaim space from all discarded
* objects.
* <p>
* The call <code>System.gc()</code> is effectively equivalent to the
* call:
* <blockquote><pre>
* Runtime.getRuntime().gc()
* </pre></blockquote>
*
* @see java.lang.Runtime#gc()
*/
public static void gc() {
Runtime.getRuntime().gc();
}
Step03:
java.lang.Runtime
/**
* Runs the garbage collector.
* Calling this method suggests that the Java virtual machine expend
* effort toward recycling unused objects in order to make the memory
* they currently occupy available for quick reuse. When control
* returns from the method call, the virtual machine has made
* its best effort to recycle all discarded objects.
* <p>
* The name <code>gc</code> stands for "garbage
* collector". The virtual machine performs this recycling
* process automatically as needed, in a separate thread, even if the
* <code>gc</code> method is not invoked explicitly.
* <p>
* The method {@link System#gc()} is the conventional and convenient
* means of invoking this method.
*/
public native void gc();
Step04:
\openjdk-8-src-b132-03_mar_2014\openjdk\jdk\src\share\native\java\lang\Runtime.c
JNIEXPORT void JNICALL
Java_java_lang_Runtime_gc(JNIEnv *env, jobject this)
{
JVM_GC();
}
Step05:
到这一步其实很明了了,无需多做解释。
\openjdk-8-src-b132-03_mar_2014\openjdk\hotspot\src\share\vm\prims\jvm.cpp
JVM_ENTRY_NO_ENV(void, JVM_GC(void))
JVMWrapper("JVM_GC");
if (!DisableExplicitGC) {
Universe::heap()->collect(GCCause::_java_lang_system_gc);
}
JVM_END
Step06:
该参数默认是false,显式设置时为true,直接跳出Full GC操作.
\openjdk-8-src-b132-03_mar_2014\openjdk\hotspot\src\share\vm\runtime\globals.hpp
product(bool, DisableExplicitGC, false, \
"Ignore calls to System.gc()") \
附录
java源码中的native方法是不能直接在jdk中看到的,因为jdk不是开源的,要看到的话需要sun授权才行,现在只有openjdk是被sun公司授权,所以要查看的话,得下载完整的OpenJDK源码包。比如此次分析用的是这个openjdk-8-src-b132-03_mar_2014.zip.