Java学习笔记——JVM垃圾回收

JVM垃圾回收主要面向JVM内存区域中的Java堆以及方法区,其中最主要的区域是堆。可以这样简单理解,对Java堆进行回收是对Java对象的回收,对方法区进行回收是对Java类(以及常量池) 的回收。

一、判断是否需要回收

1.判断对象是否需要回收

判断对象是否需要回收,不可以采用引用计数法,即有引用指向对象则计数加一,不指向它时则减一,该数字为零时可回收。这样不行,因为无法解决循环引用的问题,即有环时,则环中的对象永远无法被回收。

可达性分析法:

当一个对象对于任何GC Root不可达时,则此对象可以被回收
GC Root:
1.虚拟机栈中(栈帧中局部变量表)中引用的对象。
2.方法区中静态属性引用的对象。
3.方法区中常量引用的对象。
4本地方法栈中引用的对象。

不可达之后的对象

对象被标记为不可达之后,要检查对象的finalize()方法,如果该方法没有被重写,或者该方法已经被调用过了,则该对象必定被回收。否则,则会再调用一次finalize()方法。
finalize()方法只会被调用一次。
回收前会被标记两次。

2.引用的类型

以下由上到下引用强度依次变弱:
1.强引用 用“=”赋值 的引用是强引用,强引用永远不会被回收,哪怕OOM。
2.软引用,OOM之前会回收软引用,回收完软引用之后,内存还不够就抛出OOM。
3.弱引用,只能生存到下一次GC。
4.虚引用,不影响内存什么时候被回收,虚引用的目的是,在对象被回收前,收到一个系统通知。

3.判断方法区是否需要回收

方法区有时被称为“永久代”,其中可以回收的主要是两部分内容:废弃常量,无用的类。
没有引用常量的时候,该常量可以被回收。
可以被回收的类需要满足的条件:
1.该类所有实例被回收
2.加载该类的ClassLoader已经被回收
3.该类对应得java.lang.Class对象(反射)对象没有被引用。
可以被回收,不一定被回收。

二、垃圾收集算法

1.标记-清除算法
分为标记和清除两个阶段,首先标记处所有需要回收的对象,清除阶段进行清除。缺点:
效率低,清除结束后会有空间碎片太多

2.复制算法
将内存分为两块(或者三块),每次只使用其中一块(或两块),需要垃圾回收时,将该块中还存活的对象复制到另外一块没用的内存块中去,再将整块内存清除干净。适合新生代

3.标记-整理算法
标记过后,将所有存活的对象向一端移动,然后直接清理掉边界以外的内存。适合老年代

4.分代收集算法
把java堆根据对象存活周期分为新生代和老年代,根据各个年代的特点采用适当的收集算法。目前的商用JVM大多采用此种回收算法。

三、内存的分配与回收

内存分配的策略以及内存回收的时机与策略。
首先介绍两种GC,分别是Minor GC(新生代GC)、Major GC/Full GC(老年代GC)。
Minor GC指发生在新生代的垃圾收集,很频繁,回收的速度也比较快。
Full GC发生在老年代的GC,Full GC发生时Minor GC一般也会发生,Full GC的速度比Minor GC慢10倍。

1.对象优先在Eden(新生代)中分配

多数情况下,对象在新生代Eden区中分配。当Eden中没有足够的内存时,进行Minor GC。

2.大对象直接进入老年代

需要大量连续内存空间的Java对象,直接进入老年代,典型的是长字符串、数组。

3.长期存活的对象进入老年代

新生代中的对象,在进入Survivor区(复制算法中的)后,会有年龄,每通过一次GC,年龄+1,在达到阈值(默认15)后会进入老年代。

4.动态对象年龄判定

如果Survivor空间中相同年龄对象大小总和大于Survivor空间的一半,年龄大于等于该年龄的对象可以直接进入老年代。

5.空间分配担保(GC过程)

Minor GC前,如果老年代最大可用连续空间大于Eden中所有对象总空间,可以安全的Minor GC。否则,老年代中最大可用连续空间大于晋升老年代对象的平均大小,可尝试Minor GC,失败的话进行一次Full GC。
参考书:《深入理解Java虚拟机》

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值