规避代码级别的System.gc调用

规避代码级别的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.
* 

* Calling the gc 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. *

* The call System.gc() is effectively equivalent to the * call: *

* Runtime.getRuntime().gc()
* 
* * @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.
* 

* The name gc stands for "garbage * collector". The virtual machine performs this recycling * process automatically as needed, in a separate thread, even if the * gc method is not invoked explicitly. *

* 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.

你可能感兴趣的:(规避代码级别的System.gc调用)