所有分类
  • 所有分类
  • 未分类

JVM–Java垃圾回收的原理与触发时机

简介

说明

本文介绍Java的垃圾回收,包括:Young GC的触发时机,Full GC的触发时机,System.gc()作用。

相关网址

JVM–内存模型/垃圾回收流程 – 自学精灵

Young GC(Minor GC)

简介

Young GC(Minor GC)处理的区域是:年轻代(Eden+Survivor)。

什么时候会触发Minor GC?

  1. 大多数情况下,对象在年轻代中的Eden区进行分配,若Eden区没有足够空间,就会触发YGC(Minor GC)。

Full GC(Major GC)

简介

FGC处理的区域包括:年轻代和老年代。

什么时候会触发Full GC?

  1. 老年代的内存使用率达到了一定阈值(默认是92%  通过-XX:MaxTenuringThreshoId设置)
    1. 情景1:Survivor区进行了15次清理后还没清理的对象,则放到老年代。
      1. 次数这个阈值是可以设置的:-XX:MaxTenuringThreshold(默认是15)
    2. 情景2:Minor GC时的检查
      1. 执行Minor GC时,JVM会先检查Survivor空间是否够用
        1. 如果够用则直接进行Minor GC
        2. 如果不够用,则检查老年代最大连续可用空间是否大于新生代的总和或者历次晋升到老年代的对象的平均大小
          1. 如果大于,则直接执行Minor GC(这个时候执行是没有风险的)。
          2. 如果小于,则直接执行Full GC
      2. JDK7及之后,空间分配担保参数:-XX:HandlePromotionFailure就失效了,无需考虑这个。
    3. 情景3:使用了大对象
      1. 大对象会直接进入老年代。比如:一次加载过多数据到内存(比如SQL查询未分页),导致大对象进入老年代。
      2. 相关参数:-XX:PretenureSizeThreshold。若对象大小大于此值,就会绕过新生代, 直接在老年代中分配。
  2. 程序执行了System.gc()
    1. 只是建议JVM执行FGC,并不一定会执行
  3. jmap 加了:live参数
    1. 例如:
      1. jmap -histo:live <pid>;
      2. jmap -dump:live,format=b,file=heap.bin <pid>
  4. 其他
    1. 上一次GC之后Heap的各域分配策略动态变化
    2. RMI等的定时触发
    3. YGC时的悲观策略 

System.gc()

不要频繁使用gc函数。建议是:保持代码健壮(记得将不用的变量置为null),让虚拟机去管理内存。

System.gc():提醒虚拟机进行垃圾回收,回不回收由虚拟机决定。若虚拟机决定回收,也不是立刻进行回收,它是异步的。

当然,System.gc()也不是一点用也没有,当执行System.gc()之后,还是能一定程度影响垃圾回收的。如下所示:

package org.example.a;

class Person {

    public Person(){
        System.out.println("person created");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("gc ");
        throw new Exception("no effect");
    }
}

public class Demo {
    public static void main(String[] args) {
        Person per = new Person();
        per = null;
        System.gc();
        System.out.println("hello world");
    }
}

执行结果

person created
hello world
gc

若将System.gc()注释掉,执行结果

person created
hello world
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录