jvm垃圾回收算法

垃圾收集的第一步就是先需要算法来标记哪些是垃圾,然后再对垃圾进行处理。
 
引用计数(ReferenceCounting)算法
这种方法比较简单直观,FlashPlayer/Python使用该算法,简单高效。核心思路是,给每个对象添加一个被引用计数器,被引用时+1,引用失效-1,等于0时就表示该对象没有被引用,可以被回收。但是,Java/C#并不采用该算法,因为该算法没有解决对象相互引用的问题,即:当两个对象相互引用且不被其它对象引用时,各自的引用计数为1,虽不为0,但仍然是可被回收的垃圾对象。
 
根搜索(GC Roots Tracing)算法
基本原理是:GCRoot对象作为起始点(根)。如果从根到某个对象是可达的,则该对象称为“可达对象”(存活对象,不可回收对象)。否则就是不可达对象,可以被回收。

GC Root 引用

  1. JavaStack中的引用的对象。
  2. 方法区中静态引用指向的对象。
  3. 方法区中常量引用指向的对象。
  4. Native方法中JNI引用的对象。



垃圾收集算法

1 复制算法(copying)

内存分为两部分a,b

新生代被分配到a,a用完后,把a存活复制到b,清理a所有对象,同理b用完,复制到a

优点:简单高效,缺点 内存是只使用了一半

一般使用在新生代,适用内存分配频繁,eden:s0:s1 = 8:1:1

2 标记-整理(mark-compact)

标记存活对象

整理:将存活对象向内存开始部位移动

3 标记-清除(mark-sweep)

标记是否可回收

删除对象引用

缺点:内存空间碎片化效率不高

4 分代收集策略

Generation代
 - YongGeneration/NewGeneration:新生代,在Eden/S0/S1的存活的对象。
 - OldGeneration:老年代,在Tenured区存活的对象。
 - PermanentGeneration:永久代。
Space 区
 - Eden:伊甸园区,是新生代的一个区。
 - Survivor:幸存区,属于新生代,为了复制算法的需要。一般分成大小相等的两个区(S0/S1或者From/To)。
 - Tenured:存放老年代的区域。
 - Permanent:终身区。

 
下图:Hotspot 的 Heap 分区
 
 
下图:VisualVM 中通过 VisualGC插件显示的分区
 
 
Eden/S0/S1 新生代
[Eden                 ][S0     ][S1    ]
S0/S1是大小相当的两个区域,共同组成Survivor区。
空间比例:Eden:S0==8:1。设定方法:-XX:SurvivorRatio=8。
新生对象在Eden/S0或者Eden/S1中分配,Eden区的对象量达到一个阈值后,发生一次新生代GC。
 
Old 老年代
每个对象有“对象年龄计数器”。对象由Eden收集到Survivor区后,年龄+1。进行新生代GC后,年龄+1。依次,当年龄>=15后进入老年代。
最大年龄阈值设定:-XX:MaxTenuringThreshold。
动态年龄:如果在Survivor中所有相同年龄对象占用了空间的一半多,大于等于上述年龄的对象直接进入老年代。
大对象(比如大的数组)直接进入老年代。阈值设定:-XX:PretenureSizeThreshold。
 
Perm 永久代(PermanentGeneration)
用于存放不变对象,如类、方法、字符串等。
Java7把驻留字符串(intentd string)放到了老年代区。Java8中移除了Hotspot的永久代区。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值