JVM-垃圾回收算法

对象回收

堆分配情况

虚拟机把堆内存划分为三个区域:新生代(Young Generation),老年代(Old Generation),持久代(Permanent Generation)

回收判断

引用计数法

给对象添加一个引用计数器,没当有一个地方引用它时,计数器值就加一,当引用失效时,计数器值就减一;任何时刻计数器为0的对象就不可能再被引用了。

缺点:
1. 当对象之间存在循环引用时,会导致它们的引用计数器值都不为0,无法被回收。
2. 引用计数要求在每次因引用产生和消除的时候,需要进行一个加法和减法的操作,可能会影响系统性能

可达性分析算法

基本思想就是通过一系列称为GC Roots的对象作为起点,从这些节点开始向下搜索,搜索走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连的话,则证明此对象是不可用的。

GC Roots包括以下几种:
* 虚拟机栈(栈帧中本地变量表)中引用的对象
* 方法区中类静态属性引用的对象
* 方法区中常量引用的对象
* 本地方法栈中JNI(Native方法)引用的对象

方法区的回收

Hotspot中的永久代,永久代中的回收主要有两部分:废弃常量无用的类

废弃常量
当没有任何其他地方引用了这个字面量就可以回收了

无用的类
1. 该类的所有实例都已经被回收了,也就是Java中不存在该类的任何实例
2. 加载该类的ClassLoader已经被回收了
3. 该类对应的Java.lang.Class对象没有在任何地方呗引用,无法再任何地方通过反射访问该类的方法。

虚拟机可以对满足上诉三个条件的类进行回收,但并不是和对象一样,不使用了就回收。

在大量使用反射,动态代理,CGLib等ByteCode框架,动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的能力,以保证永久代不会溢出。

垃圾收集算法

标记-清除(Mark-Sweep)

两个阶段:①标记出所有需要回收的对象,②标记完成后,统一进行回收

缺点:
1. 效率问题:标记和清除的效率都不高
2. 标记清除将会产生大量不连续的内存碎片,空间碎片太多将会导致分配大对象的时候,没有足够的连续空间,不得不提前触发垃圾回收动作

复制(Copying)

将可用内存分为两块,每次只使用其中一块,当这一块使用完后,就将还活着的对象复制到另一块上去,之后,清除正在使用的这边的内存块中的对象,然后,交换两个内存的角色,不用考虑内存碎片等问题。

新生代串行回收器采用这种算法(因为垃圾对象通常多于存活对象)来回收,Eden 8 ,from 1 ,to 1。

标记-整理(Mark-Compact)

标记过程和标记-清除算法一样,后面不是对可回收对象直接进行清理,而是让存活的对象都移动到一端,然后将边界以外的直接清理掉。

标记-整理适合发生在老年代,大部分对象都是存活对象。如果用复制算法,复制成本较高。

分代算法(Generational Collecting)

复制,标记-清除和标记-整理,都没办法完全替代其他算法,他们有各自的优缺点。

分代算法,它将内存区间根据对象的特点分成几块,根据每块内存区间的特点,使用不同的回收算法。以提高垃圾回收的效率。新生代使用复制算法,老年代使用标记-清除或者标记-清理

新生代回收频率高,耗时段,老年代回收频率低,耗时长。为了适应新生代的回收,虚拟机使用一种叫卡表(Card Table)的数据结构。卡表是一个比特位集合。每一位可以表示4KB的老年代区域,是否持有新生代对象的引用,当标记位为0,表示不持有,为1的时候表示持有。当垃圾回收时,只需要扫描卡表标记位为1 的区域,可以大幅提高效率。

这里写图片描述

分区算法(Region)

分区算法将整个堆空间分为连续的不同的小区,每一个小区独立使用,独立回收,这种算法好处可以控制一次回收多少个小区域。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值