二、GC 回收机制与分代回收策读后感
2020-04-06 本文已影响0人
XII01
什么是垃圾
所谓垃圾就是内存中已经没有用的对象。 既然是”垃圾回收",那就必须知道哪些对象是垃圾。Java 虚拟机中使用一种叫作"可达性分析”的算法来决定对象是否可以被回收。
可达性分析
可达性分析算法是从离散数学中的图论引入的,JVM把内存中所有的对象之间的引用关系看作一张图,通过一组名为”GCRoot"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,通过判断对象的引用链是否可达来决定对象是否可以被回收。
GC Root 对象
- Java 虚拟机栈(局部变量表)中的引用的对象。
- 方法区中静态引用指向的对象。
- 仍处于存活状态中的线程对象。
- Native 方法中 JNI 引用的对象。
什么时候回收
- Allocation Failure:在堆内存中分配时,如果因为可用剩余空间不足导致对象内存分配失败,这时系统会触发一次 GC。
- System.gc():在应用层,Java 开发工程师可以主动调用此 API 来请求一次 GC。
如何回收垃圾
标记清除算法(Mark and Sweep GC,分为以下两个阶段
- Mark 标记阶段:找到内存中的所有 GC Root 对象,只要是和 GC Root 对象直接或者间接相连则标记为灰色(也就是存活对象),否则标记为黑色(也就是垃圾对象)。
- Sweep 清除阶段:当遍历完所有的 GC Root 之后,则将标记为垃圾的对象直接清除。
- 优点:实现简单,不需要将对象进行移动。
- 缺点:这个算法需要中断进程内其他组件的执行(stop the world),并且可能产生内存碎片,提高了垃圾回收的频率。
复制算法(Copying)
将现有的内存空间分为两快,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中。之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
- 优点:按顺序分配内存即可,实现简单、运行高效,不用考虑内存碎片。
- 缺点:可用的内存大小缩小为原来的一半,对象存活率高时会频繁进行复制。
标记-压缩算法 (Mark-Compact)
- Mark 标记阶段:找到内存中的所有 GC Root 对象,只要是和 GC Root 对象直接或者间接相连则标记为灰色(也就是存活对象),否则标记为黑色(也就是垃圾对象)。
- Compact 压缩阶段:将剩余存活对象按顺序压缩到内存的某一端。
分代回收的中心思想就是:对于新创建的对象会在新生代中分配内存,此区域的对象生命周期一般较短。如果经过多次回收仍然存活下来,则将它们转移到老年代中。
GC Log 分析
- 新生代 GC:这一区域的 GC 叫作 Minor GC。因为 Java 对象大多都具备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度也比较快。
- 老年代 GC:发生在这一区域的 GC 也叫作 Major GC 或者 Full GC。当出现了 Major GC,经常会伴随至少一次的 Minor GC。