Java内存回收收集器

JVM通过GC来回收堆和方法区中的内存,GC的基本原理首先会找到程序中不再被使用的对象,然后回收这些对象所占用的内存,通常采用收集器的方式实现GC,主要的收集器有引用计数收集器和跟踪收集器

1.引用计数收集器

引用计数收集器采用的分散式的管理方式,通过计数器记录对象是否被引用。当计数器为零时,说明此对象不再被使用。于是可以进行回收。

引用计数收集器每次对象赋值时进行引用计数器增减,它有一定的消耗。另外引用计数收集器对于循环引用的场景没有办法实现回收。因此对于Java这种面向对象的语言会形成复杂引用关系,引用计数收集器不是非常适合,Sun JDK在实现GC时也未采用这种方式。

2.跟踪收集器

跟踪收集器采用的为集中式的管理方式,全局记录数据的引用状态。基于一定条件的触发(例如:定时,空间不足时),执行时需要从根集合扫描对象的引用关系,这可能会造成应用暂停,主要有:复制 (Copying),标记-清除(Mark Sweep),标记-压缩(Mark-Compact)三种实现算法。

复制(Copying)

复制采用的方式为从跟集合扫描出存活的对象,并将找到的存活对象复制到一块新的完全未使用的空间中。

复制收集器方式仅需从跟集合扫描所有存活的对象,当要回收的空间中存活对象较少时,复制算法会比较高效,其带来的成本是要增加一块空的内存空间及对象移动。

标记-清除(Mark Sweep)

标记清除采用的方式为从跟集合开始扫描,对存活的对象进行标记,标记完毕后,在扫描整个空间中未标记的对象,并进行回收。

标记清除动作不需要进行对象移动,且仅对不存活对象进行处理。在空间中存活对象较多的情况下较为高效,但由于标记清除采用的为直接回收不存活对象所占用内存,因此会造成内存碎片。

标记-压缩(Mark Compact)

标记-压缩采用和标记清除一样的方式对存活对象进行标记,但在清除时则不同,在回收不存活对象所占用内存空间后,会将其他所存活对象都往左端的空间进行移动,并更新引用其对象的指针。

标记压缩在标记清除的基础上还需进行对象移动,成本相对较高,好处则是不产生内存碎片。

--------------------------------------------------------------


跟搜索算法

在主流的商用语言中(JAVA,C# 甚至包括古老的LISP),都是使用跟搜索算法(GCRoots Tracing) 判定对象是否存活。这个算法的基本思路是通过一系列的名为GC Roots 的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots 没有任何引用链相连(从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

在Java语言中,可以作为GC Roots 的对象包括下面几种:

1.虚拟机栈(栈帧中得本地变量表)中引用的对象。

2.方法区中得类静态属性引用的对象。

3.方法区中得常量引用的对象

4.本地方法栈中JNI(Native方法)引用的对象


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值