JVM垃圾回收

1.哪些内存需要回收?

1.1.一次标记(可达性分析算法)

有一系列“GCRoots”起点,从这些点开始向下搜索,走过的路径称为“引用链”。若一个对象没有任何引用链可到达GC Roots,那么该对象就是不可用的,即使该对象还与其他对象相关联。

GC Roots类型:

①   虚拟机栈中引用的对象

②   方法区中类静态属性引用的对象

③   方法区中常量引用的对象

④   本地方法栈中引用的对象

经可达性分析算法所标记出的对象,会进行一次标记,但是这并不意味着非死不可,要真正搞死一个对象,至少要经历两次标记。

1.2.二次标记(死缓)

经可达性分析算法所标记出的对象,会进行一次筛选(根据finalize方法)。若经过筛选,判定可回收,那么就会立即回收;若判定没有必要回收,那么就将对象放入F-Queue队列中,进行二次筛查。

二次筛查会执行对象的finalize()方法。若对象在这个过程重新与引用链上的任何一个对象建立关联,那么该对象就会从回收集合中移除。否则,对象会被回收。

2.什么时候回收?

(1)程序调用System.gc时可以触发;

(2)系统自身来决定GC触发的时机:

系统判断GC触发的依据:根据Eden区和From Space区的内存大小来决定。当内存大小不足时,则会启动GC线程并停止应用线程。

3.怎么回收?

为了让内存回收更加高效,目前主流的JVM(HotSpot)采用的是分代收集算法,从Sun JDK 1.2开始对堆采用了分代管理方式,如下图所示:

3.1新生代(Minor GC/Young Generation)

对象在被创建时,内存首先是在年轻代进行分配(注意,大对象可以直接在老年代分配)。当年轻代需要回收时会触发Minor GC(也称作Young GC)。

实际情况下,98%的对象都是存活率为0,所以可以将运行时的内存(即第2点中的第一块内存)所占用的比例调整大一点。年轻代由Eden Space和两块相同大小的Survivor Space(又称From Space和To Space)构成,Eden区和Servior区的内存比为8:1:1。所以在新生代中采用复制算法,这样可用内存就占到新生代总容量的90%。

当S1空间满了,则会将对象移到老年代。而且复制算法会对每次存活下来的对象计数,如果存活次数到达一定阈值(默认15),则也会将对象移到老年代。

3.2老年代

与新生代不同的是,老年代对象存活率较高,这时采用复制算法,效率将会变低。老年代采用标记-整理算法:

  1. 标记出所有需要回收的对象
  2. 所有存活的对象都向一端移动
  3. 清理边界以外的内存

3.3永久代

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。

请参考下Java8:从永久代到元数据区 
(译者注:Java8中已经移除了永久代,新加了一个叫做元数据区的native内存区)

参考:

https://blog.csdn.net/fyyyr/article/details/79389222

https://blog.csdn.net/weixin_39788856/article/details/80388002

https://blog.csdn.net/qq_32521313/article/details/78892555

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值