Java垃圾收集器与内存分配策略之垃圾收集算法

本篇内容为本人在阅读《深入解析Java虚拟机JVM高级特性与最佳实践 第二版》的笔记,相关内容主要来源于该书籍

对象存活判断算法

1.引用计数法:
给对象中提那家一个引用计数器,每当一个地方引用它时,计数器值就加1;当引用失效时,计数器就减1;任何时候计数器为0的对象就是不可能再被使用的。
但是它很难解决对象之间相互引用的问题,所以主流的Java虚拟机中没有选用此算法来管理内存。

2.可达性分析法:
基本思路为通过一系列成为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。
Java中可作为GC Roots的对象:
1.虚拟机栈(栈帧的本地变量表)中引用的对象
2.方法区中类静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈中JNI(即一般说的Native方法)引用的对象

引用扩充分类
1.强引用:类似“Object obj = new Object()”类的引用,只要强引用还存在,对象就不会被回收。
2.软引用:还有用但不是非必需的对象,下次内存溢出前会被回收。
3.弱引用:非必需对象,下次垃圾回收时被回收。
4.虚引用:不会影响对象的生存时间,也无法使用虚引用取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。

生存还是死亡
真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”;finalize()方法是对象逃脱死亡命运的最后一次机会,任何一个对象的finalize()方法都只会被系统自动调用一次。
但是finalize()能做的所有工作,使用try-finally或者其他方式都可以做的更好,更及时,所以不建议使用这个方法。

垃圾收集算法

标记-清除算法:
分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
主要不足有两个:一个是标记和清除的效率都不高;另一个是标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象是,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

复制算法:
现在的商业虚拟机都用这种收集算法来回收新生代,它将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor空间。当回收时,将Eden和Survivor中还存活着的对象一次性地复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间,当Survivor空间不够时,需要依赖其他内存(这里指老年代)进项分配担保。

标记-整理算法:
用于回收老年代,标记过程与“标记-清理算法”一样,但后续算法不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后清理掉边界意外的内存。

分代收集:
并没有新的思想,只是商业虚拟机都采用的根据各个年代的特点采用最适当的收集算法。

本章内容及重点知识部分较多,因此计划分为多篇,便于阅读,
码字不易,感谢阅读

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值