JVM基础知识之垃圾回收

一 可达性分析方法

在Java虚拟机中定义了一些不会被回收的对象,叫做GcRoots,从GcRoot中出发,标记可以到达的对象,如果对象可以被标记,这个对象就还是存活的,否则就是需要被回收的

1.1GCRoots的分类

虚拟机栈中的对象
本地方法栈中的对象
方法区中常量引用的对象
方法区中静态属性引用的对象
被同步锁持有的对象
临时性加入的对象

1.2 引用的分类

强引用: 被new出来的对象,在内存不够的时候也不会被回收,而是抛出异常
软引用: 一些有用但是非必须的对象,在内存不够的时候会把这些对象放入到垃圾回收器中清理,如果清理完成后内存依旧的话,就会报异常
弱引用: 引用关系比软引用更弱一点,被引用关联的对象只能生存到下一次垃圾回收之前,在垃圾回收的时候,无论内存是否充足都会回收了只被弱引用引用的对象
虚引用:虚引用的存在对对象的生命周期没有任何关系,设置的目的是为了在JVM进行垃圾回收该对象时候收到一个系统通知

1.3 对象被回收的过程

对象回收的时候需要被标记两次,一次是GC标记,另一次是对这个对象进行一个筛选,筛选这个对象是否覆盖finalize()方法,

  • 如果覆盖了finalize()方法,会把这个对象放入到F-Queue的队列中去,并且通过一个jvm创建一个Finalizer线程去执行对象中的finalize()方法,执行完成后
  • 如果没有实现finalize()方法,就直接进行回收
    建议对象不要实现finalize()方法,因为这样子会导致内存回收速度变慢,在极端情况下可能导致内存泄露

二 垃圾回收算法

2.1 分代收集理论

垃圾回收主要建立在以下三个理论中:
1)弱分代假说: 假设全部的对象都是朝生夕灭的
2)强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。
3) 跨代引用假说:跨代引用相对于同代引用来说仅占极少数。

2.2 垃圾回收算法

2.2.1 标记-清除算法

含义:
标记存活的对象,对未被标记的对象进行统一回收或者
标记需要回收的对象,统计进行回收
使用范围:
老年代
优点和缺点:
优点是实现简单,缺点是垃圾回收完成后有垃圾碎片产生

2.2.2 标记-复制算法

含义:
将内存分为两部分,每次只使用一部分
1.标记存活的对象
2.移动存活的对象到没有使用的内存中
3.清理掉不存活的对象
使用范围:
新生代
优点和缺点:
缺点是对内存的利用率不高
优点是每次回收的时候没有内存碎片的问题

2.2.3 标记整理算法

含义:
1.标记出来存活的对象
2.将存活的对象放在内存的一侧
3.清理边界外的内存中的对象
使用范围:
老年代
优点和缺点:
优点是没有内存碎片,缺点是每次回收的时候需要进行整理.CMS牢记回收器可以指定在进行了多少次标记-清除算法之后,进行一次标记整理

三 垃圾回收算法中的名词

根节点枚举
在GC的时候不需要到方法区中找对应的GCRoot,GCRoots的信息存储器OopMap的一个HashMap中
安全点
Java线程自己到某一个位置挂起来,进行垃圾回收的Stop-The-World操作
安全区域
Java线程在某一个区域中,引用关系不会变化,这个区域叫做安全区域(线程被阻塞的情况),当退出安全区域的时候,需要检测Java虚拟机是否已经完成了根节点枚举,如果已经完成了,就继续执行,否则会被挂起来
记忆卡集
为了解决跨代引用,引出的记忆卡集,记忆卡集是一个字节数组.
在这里插入图片描述
在这里插入图片描述
只要卡页中存在一个跨代引用,就把卡表的数组元素设置为1,称这个元素变脏,没有标志就为0.为1的地址会被一起放在GCRoot中进行遍历,

四 并发的可达性分析

在GCRoots被选举出来后,就需要分析哪一些对象是存活的,哪一些对象是不能到达的,这里使用的三色标记法
黑色:对象已经被扫描过,并且它的应用的对象都已经被扫描过
灰色:对象已经被扫描过,但是它的对象还没有完成被扫描过
白色: 对象还没有被扫描
在标记过程中,原本存活的垃圾被标记为回收,这种情况是错误的,JVM经过分析后得到以下两个结论都被满足的时候,才会发现"对象消失的问题"
1)黑色对象直接指向了白色对象
2)上面这个白色对象连接的灰色对象的引用被删除了
针对条件一,JVM提出了增量更新的方案,就是在黑色对象指向白色对象的时候,将这个黑色对象记录下来,后续再次进行扫描
针对条件二,JVM提出了原始快照的方案,就是将灰色对象删除的引用关系记录下来,下一次再进行扫描

五 经典的垃圾回收器

在这里插入图片描述 垃圾回收器

5.1 Serial收集器

5.1.1 Serial收集器

作用范围
使用在了新生代中,已经已经不使用了,可以配置CMS使用
回收垃圾的过程
只有一个线程去回收垃圾,需要暂停全部线程
采用的垃圾回收算法
新生代使用的是复制算法

5.1.2 SerialOld收集器

作用范围
使用在老年代中,是CMS垃圾回收器后备使用的垃圾回收器
回收垃圾的过程
只有一个线程去回收垃圾,需要暂停全部线程
采用的垃圾回收算法
老年代使用的是标记-整理算法

5.2 Parallel系列收集器

5.2.1 parNew

作用范围
使用在新生代中配合CMS使用
回收垃圾的过程
有多个线程去回收垃圾,需要暂停用户线程
采用的垃圾回收算法
新生代采用复制算法

5.2.2 Parallel Scavenge收集器

作用范围
使用在新生代,关注点是程序的吞吐量
在这里插入图片描述
回收垃圾的过程
有多个线程去回收垃圾,需要暂停用户线程
采用的垃圾回收算法
标记-复制算法回收新生代

5.2.3 Parallel Old收集器

作用范围
使用在老年代,配合Parallel Scavenge使用
回收垃圾的过程
有多个线程去回收垃圾,需要暂停用户线程
采用的垃圾回收算法
标记清除算法

5.3 CMS收集器

CMS收集器是一个以获取最短回收停顿时间为目标的收集器.垃圾回收分为以下四个过程:
初始标记
需要stop-the-world,就是标记一个GC Roots能够关联上的对象,速度很快
并发标记
从GCRoots开始的直接关联对象开始遍历整个图的过程,可以和用户线程并行
重新标记
为了修正并发标记期间,因为程序运行导致标记发生变化的那一部分的标记记录
并发清理
清理掉已经判断死亡的对象
在这里插入图片描述

5.3.1 CMS的缺点

浮动垃圾无发处理
CMS无法处理浮动垃圾,有可能导致"Con-currentMode Failure"失败进而导致另一次完全的"Stop The World"的Full GC的产生.在CMS的并发标记阶段和并发清理阶段.用户线程还是在运行的,程序还会伴随着新的垃圾对象不断的产生,但是这一个垃圾对象是出现在标记过程结束以后,CMS无发在当次垃圾回收中处理掉它,只能留着下一次垃圾收集时候再清理掉.
并发失败Concurrent Mode Failure
CMS运行期间预留的内存没有办法满足程序分配新对象的需要,就会出现一次并发失败,这个时候虚拟机将必须启动后备预案:冻结用户线程执行,临时启用Serial Old收集器来进行重新进行老年代的垃圾收集,可以通过-XX:CMSInitiatingOccupancyFraction设置当内存达到多少时候,进行一次垃圾回收,默认是92%
内存碎块
CMS是通过"标记-清除"算法实现的收集器,会有垃圾碎片,-XX:CMSFullGCsBefore-Compaction设置经过多少次,下一次进入到Full Gc前需要先进行垃圾碎片的回收

5.4 G1收集器

G1收集器不再根据分代回收垃圾,而是将内存分为一小块,哪一块内存回收后效益最高,就回收哪一块
在这里插入图片描述
E和S是新生代的Eden和Survivor空间,H是老年代
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值