内存溢出分析之垃圾回收知识

一.Java 内存区域划分

Java内存区域划分
图片来源Java虚拟机规范
除上图运行时数据区域之外,还有一块内存区域被频繁的使用,那就是直接内存,未定义在 《Java虚拟机规范中》中。

二.垃圾回收

1.可达性分析:

当一个对象到 GC Roots 没有任何引用链时,即从 GC Roots 到这个对象不可达,则说明该对象不可用,可被垃圾回收器回收。

注:如果类实现了 finalize() 方法,则被回收前会先调用该方法,且只会调用一次。

2.垃圾收集算法:

标记清除 (Mark-Sweep)

标记出所有需要回收的对象,标记完成后统一回收被标记的对象。

主要缺点:效率不高;产生大量内存碎片。内存碎片太多可能会导致分配较大对象时,找不到连续内存而触发 GC。

复制 (Copying)

将内存划分为大小相等的两块,每次只使用其中一块。当这块内存用完了,则将存活对象复制到另一块上,然后将已使用的内存空间一次清理掉。适用于多用于新生代。

优点:算法简单高效,且无内存碎片
缺点:牺牲了空间

标记整理 (Mark-Compact)

标记出需要回收的对象,让所有存活的对象都向一端移动,然后清理掉端另一边的内存。

分代收集算法

根据对象存活周期的不同,将内存分为几块。一般为新生代和老年代(jdk 1.8移除了永久代)。新生代存活对象少,采用复制算法;老年代对象存活率高,采用标记-清除或标记-整理算法。

IBM 研究表明,新生代中 98% 对象存活率很低,所以不需要按照 1:1 的比例来划分内存空间,而是使用一块较大的 Eden 区和两块较小的 Survivor 区,每次 YGC 时将 Eden 区和其中一块 Survivor 区的存活对象复制到另一个 Survivor 区,再一次性清除 Eden 区和使用过的 Survivor 区。

Eden 区和 Survivor 区默认比例大小为 8:1,牺牲 Young 区10%的空间,可通过 SurvivorRatio 参数指定。

3.垃圾收集器

HotSpot 虚拟机的垃圾收集器(图片网上找的):
垃圾收集器种类
如果两个收集器之间存在连线,则说明它们可以搭配使用。

3.1 CMS 收集器

基于标记-清除算法。只有 CMS initial markCMS Final Remark 阶段会 Stop The World

初始标记(CMS initial mark)

标记那些直接被 GC Roots 引用或者被年轻代存活对象所引用的所有对象,会 Stop The World

并发标记(CMS concurrent mark)

遍历整个 old 区,并发标记存活对象。和应用线程并行执行,此时有些对象可能会改变可达状态。

并发预清理(CMS concurrent preclean)

并发阶段,和应用线程并行执行。在前面并发执行的阶段中,有些对象的引用可能会发生变化,JVM 会将包含该对象的区域 (Card) 标记为 Dirty (即 Card Marking)。

pre-clean 阶段,那些能从 Dirty Card 对象到达的对象也会被标记,标记完成之后,Dirty Card 标记会被清除。

此外,还会执行一些必要的清理和为 Final Remark 阶段做一些准备工作。

并发预清理(CMS concurrent abortable preclean)

并发执行,这个阶段会尽可能的减轻 Final Remark 阶段 Stop The World 的压力。

这个阶段的时间依赖于很多因素,会重复做相同的事情,直至满足一些条件,如:重复的次数、有效的工作量、始终时间等。

重新标记(CMS Final Remark)

完成标记整个 old 区所有的可达对象,会 Stop The World

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值