004-四、GC 性能优化 – GC 算法(基础篇)
除了对作者表示感谢外,还需要感谢译者【铁锚】,谢谢两位的付出
出处:https://blog.csdn.net/renfufei/column/info/14851
相关术语翻译说明:
Mark
,标记;
Sweep
,清除;
Compact
,整理; 也有人翻译为压缩,译者认为 GC
时不存在压缩这回事。
Copy
,复制; copy
用作名词时一般翻译为拷贝/副本,用作动词时翻译为复制。
本章简要介绍 GC
的基本原理和相关技术, 下一章节再详细讲解 GC
算法的具体实现。各种垃圾收集器的实现细节虽然并不相同,但总体而言,垃圾收集器都专注于两件事情:
- 查找所有存活对象
- 抛弃其他的部分,即死对象,不再使用的对象。
第一步, 记录(census
)所有的存活对象, 在垃圾收集中有一个叫做 标记(Marking
) 的过程专门干这件事。
标记可达对象(Marking Reachable Objects)
现代JVM中所有的GC算法,第一步都是找出所有存活的对象。下面的示意图对此做了最好的诠释:
首先,有一些特定的对象被指定为 Garbage
Collection
Roots
(GC
根元素)。包括:
- 当前正在执行的方法里的局部变量和输入参数
- 活动线程(
Active
threads
) - 内存中所有类的静态字段(
static
field
) - JNI引用
其次,GC
遍历(traverses
)内存中整体的对象关系图(object
graph
),从GC
根元素开始扫描, 到直接引用,以及其他对象(通过对象的属性域)。所有GC
访问到的对象都被标记(marked
)为存活对象。
存活对象在上图中用蓝色表示。标记阶段完成后, 所有存活对象都被标记了。而其他对象(上图中灰色的数据结构)就是从 GC
根元素不可达的, 也就是说程序不能再使用这些不可达的对象(unreachable
object
)。这样的对象被认为是垃圾, GC
会在接下来的阶段中清除他们。
在标记阶段有几个需要注意的点:
在标记阶段,需要暂停所有应用线程, 以遍历所有对象的引用关系。因为不暂停就没法跟踪一直在变化的引用关系图。这种情景叫做 Stop The World pause (全线停顿),而可以安全地暂停线程的点叫做安全点(safe point), 然后, JVM就可以专心执行清理工作。安全点可能有多种因素触发, 当前, GC是触发安全点最常见的原因。
此阶段暂停的时间, 与堆内存大小,对象的总数没有直接关系, 而是由存活对象(alive objects)的数量来决定。所以增加堆内存的大小并不会直接影响标记阶段占用的时间。
标记 阶段完成后, GC进行下一步操作, 删除不可达对象。
删除不可达对象(Removing Unused Objects)
各种 GC
算法在删除不可达对象时略有不同, 但总体可分为三类: 清除(sweeping
)、整理(compacting
)和复制(copying
)。下一章节将详细讲解这些算法。
Sweep(清除)
Mark
and
Sweep
(标记-清除) 算法的概念非常简单: 直接忽略所有的垃圾。也就是说在标记阶段完成后, 所有不可达对象占用的内存空间, 都被认为是空闲的, 因此可以用来分配新对象。
这种算法需要使用 空闲表(free-list
),来记录所有的空闲区域, 以及每个区域的大小。维护空闲表增加了对象分配时的开销。此外还存在另一个弱点 —— 明明还有很多空闲内存, 却可能没有一个区域的大小能够存放需要分配的对象, 从而导致分配失败(在 Java
中就是 OutOfMemoryError
)。
Compact(整理)
标记-清除-整理算法(Mark-Sweep-Compact
), 将所有被标记的对象(存活对象), 迁移到内存空间的起始处, 消除了标记-清除算法的缺点。
相应的缺点就是 GC
暂停时间会增加, 因为需要将所有对象复制到另一个地方, 然后修改指向这些对象的引用。此算法的优势也很明显, 碎片整理之后, 分配新对象就很简单, 只需要通过指针碰撞(pointer bumping
)即可。使用这种算法, 内存空间剩余的容量一直是清楚的, 不会再导致内存碎片问题。
Copy(复制)
标记-复制算法(Mark and Copy) 和 标记-整理算法(Mark and Compact) 十分相似: 两者都会移动所有存活的对象。区别在于, 标记-复制算法是将内存移动到另外一个空间: 存活区。标记-复制方法的优点在于: 标记和复制可以同时进行。缺点则是需要一个额外的内存区间, 来存放所有的存活对象。
写完了如果写得有什么问题,希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")
看完两件小事
如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:
- 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
- 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
本文著作权归作者所有,如若转载,请注明出处
转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com