天天看点

java垃圾回收那点事(一) System.gc开始说起

java提供了从语言角度能够强制jvm进行垃圾回收,在我们的程序中可以通过调用System.gc去强制jvm进行垃圾回收,通过源码我们可以看到实际上是调用了Runtime去强制gc

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

Runtime的gc方法是native方法也就是Rumtime.c中的

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

而JVM_GC方法是在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
           

我们看到参数DisableExplicitGC,从代码中可以使用-XX:+DisableExplicitGC 可以关闭system,gc

对universe:heap() -> Universe::_collectedHeap 是在初始化的时候决定使用什么类型的heap,也决定了使用什么gc的策略,也就是说java heap的分配方式是在java启动的时候就决定的,无法中间更改,同样对应的gc策略也无法更改

if (UseParallelGC) {
#ifndef SERIALGC
    Universe::_collectedHeap = new ParallelScavengeHeap();
#else  // SERIALGC
    fatal("UseParallelGC not supported in java kernel vm.");
#endif // SERIALGC

  } else if (UseG1GC) {
#ifndef SERIALGC
    G1CollectorPolicy* g1p = new G1CollectorPolicy_BestRegionsFirst();
    G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
    Universe::_collectedHeap = g1h;
#else  // SERIALGC
    fatal("UseG1GC not supported in java kernel vm.");
#endif // SERIALGC

  } else {
    GenCollectorPolicy *gc_policy;

    if (UseSerialGC) {
      gc_policy = new MarkSweepPolicy();
    } else if (UseConcMarkSweepGC) {
#ifndef SERIALGC
      if (UseAdaptiveSizePolicy) {
        gc_policy = new ASConcurrentMarkSweepPolicy();
      } else {
        gc_policy = new ConcurrentMarkSweepPolicy();
      }
#else   // SERIALGC
    fatal("UseConcMarkSweepGC not supported in java kernel vm.");
#endif // SERIALGC
    } else { // default old generation
      gc_policy = new MarkSweepPolicy();
    }

    Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
  }
           

从源码中我们可以看到

Parallel GC 是用的是ParallelScavengeHeap, 

CMS 使用的是 GenCollectdHeap 

G1使用的是G1CollectedHeap