垃圾收集器与内存分配策略(上)

本文深入探讨了Java内存管理中的垃圾收集机制,包括引用计数和可达性分析两种对象存活判断算法,以及强引用、软引用、弱引用和虚引用四种引用类型。此外,介绍了标记-清除、复制、标记整理和分代收集四种垃圾收集算法,以及如何针对不同年代的对象采取不同的策略。同时,提到了方法区的回收,特别是废弃常量和无用类的清理,并讨论了内存碎片和内存溢出问题。
摘要由CSDN通过智能技术生成

当需要排查各种内存溢出,内存泄露问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。

1.在对里面存放着Java世界几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”(即不可能再被任何途径使用的对象)

(1)引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。(引用计数算法的实现简单,判定效率也很高,但是主流的Java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题)
(2)可达性分析算法
这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象时不可用的。
在Java语言中,可作为GC Roots的对象包括下面几种:
·虚拟机栈(栈帧中的本地变量表)中引用的对象
·方法区中类静态属性引用的对象
·方法区中常量引用的对象
·本地方法栈中JIN(即一般说的Native方法)引用的对象
(3)引用
如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。
引用分为强引用、软引用、弱引用、虚引用4种,4种引用强度依次逐渐减弱。
·强引用就是指在程序代码中普遍存在的,类似“Object obj = new Object”,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象
·软引用是用来描述一些还有用但并非必须的对象。在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常
·弱引用也是用来描述非必须对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象
·虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。为一个对象设置虚引用关联的目的就是能在这个对象被收集器回收时收到一个系统通知
(4)回收方法区
在堆中,尤其是在新生代中,常规应用进行一次垃圾收集一般可以回收70%~95%的空间,而永久代的垃圾收集效率远低于此
永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类。
如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,按它将会被第一次标记并且进行一次筛选,筛选的条件就是此对象是否有必要执行finalize()方法。

2.垃圾收集算法

(1)标记-清除算法
最基础的收集算法是“标记-清除”算法,如同它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
它的主要不足有两个:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作
(2)复制算法
为了解决效率问题,一种称为“复制”的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
复制算法在对象存活率较高时就要进行较多的复制操作,效率将会变低
(3)标记整理算法
标记过程与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一边移动,然后直接清理掉端边界以外的内存。
(4)分代收集算法
当前商业虚拟机的垃圾收集都采用“分代收集”算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块,一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适合的收集算法。
在新生代中每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选择复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或者“标记-整理”算法来进行回收。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值