JVM 基础 (4) -- System.gc()

1. System.gc() 的作用

System.gc() 的作用是建议虚拟机进行一次 Full GC,但是虚拟机可以拒绝这个 GC 请求。

GC 线程是一种守护线程

2. System.gc() 源码

/**
* Indicates to the VM that it would be a good time to run the
* garbage collector. Note that this is a hint only. There is no guarantee
* that the garbage collector will actually be run.
*/
public static void gc() {
    boolean shouldRunGC;
    synchronized(lock) {
        shouldRunGC = justRanFinalization;
        if (shouldRunGC) {
            justRanFinalization = false;
        } else {
            runGC = true;
        }
    }
    if (shouldRunGC) { //justRanFinalization=true
        Runtime.getRuntime().gc();
    }
}

从源码可以看出,只有当justRanFinalization=true的时候才会执行垃圾收集。
而当调用runFinalization()的时候,justRanFinalization 会变为 true

/**
* Provides a hint to the VM that it would be useful to attempt
* to perform any outstanding object finalization.
*/
public static void runFinalization() {
       boolean shouldRunGC;
       synchronized(lock) {
           shouldRunGC = runGC;
           runGC = false;
       }
       if (shouldRunGC) {
           Runtime.getRuntime().gc();
       }
       Runtime.getRuntime().runFinalization();
       synchronized(lock) {
           justRanFinalization = true;
       }
}

其实当我们直接调用System.gc()只会把这次 GC 请求记录下来,等到justRanFinalization=true的时候才会去执行 GC,justRanFinalization=true之后会允许一次system.gc()。之后再 call System.gc()时还会重复上面的行为。
所以System.gc()要跟System.runFinalization()要一起搭配使用才能确保虚拟机执行垃圾收集。

查看ZygoteInit.java,发现gc()runFinalizationSync()是配合使用的,这样才有效果

ZygoteInit 是 c 到 java 的入口,也是 java 的第一个进程
它的 main 方法主要做了三件事:

  1. 建立 socket 服务端
  2. 启动各种系统服务如 ams,wms,pms…
  3. 进入死循环,等待和处理 ams 通过 socket 传递的请求

想要了解 ZygoteInit 可以点这里

static void gcAndFinalize() {

   final VMRuntime runtime = VMRuntime.getRuntime();

   /* runFinalizationSync() lets finalizers be called in Zygote,
   * which doesn't have a HeapWorker thread.
   */
   System.gc();
   runtime.runFinalizationSync();
   System.gc();
}

3. 如何保证 System.gc() 有效

执行以下代码即可

System.gc();
System.runFinalization();
System.gc();

不过不建议这么做,因为 JVM 有自己的 GC 策略,根本不需要我们手动申请 GC

4. System.gc() 与 Runtime.getRuntime().gc() 的区别

  1. 垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,当一个对象不再被引用的时候,按照特定的垃圾收集算法来实现资源自动回收的功能。
  2. 每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime()方法获取当前运行时。
  3. java.lang.System.gc()实际上也是调用了java.lang.Runtime.getRuntime().gc(),两者的行为没有任何不同。
    public static void gc() {
        Runtime.getRuntime().gc();
    }
    
  4. 唯一的区别就是System.gc()写起来比Runtime.getRuntime().gc()简单点。其实基本没什么机会用到这个命令,因为这个命令只是建议 JVM 安排 GC 运行,还有可能完全被拒绝。 GC 本身会周期性的自动运行,由 JVM 决定运行的时机,而且现在的 JVM 版本有多种更智能的模式可以选择,还会根据运行的机器自动去做选择,就算真的有性能上的需求,也应该去对 GC 的运行机制进行微调,而不是通过使用这个命令来实现性能的优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值