最近在重新看JVM的内容,这篇文章重新梳理一下垃圾回收中的相关内容。
Java中的垃圾回收(Garbage Collection, GC)指的是回收堆和方法区中不再使用被使用到的对象,即垃圾。
GC中需要考虑的三个主要问题:
- 什么是垃圾:即哪些对象可以被定义为垃圾
- 何时回收
- 如何回收
本文将针对上述三个问题一一解答。
什么是垃圾?
这里就涉及到两种判断对象是否存活的算法:
引用计数法
给每个对象添加一个计数器,当它被某些地方引用是,计数器加一,引用失效时,计数器减一,那些计数器为零的对象就是垃圾了。这种方法的一个关键问题是会出现循环引用,即对象A里面的成员引用了对象B,而对象B里面的成员又引用了对象A
可达性分析算法
通过一系列成为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索走过的路径叫做引用链,当一个对象到GC Roots没有任何引用链相连时,则说明这个对象不可用。
那么问题来了,什么是GC Root,哪些对象可以成为GC Root?
在Java中,可以作为GC Root的对象包括以下几种:
- 虚拟机栈中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
其实上面的GC Root也是有规律可循的,分为两种:一种是栈中引用的对象(包括虚拟机栈和本地方法栈),一种则是方法区中的静态属性和常量引用的对象
如何回收
标记清除算法
内存碎片过多
复制算法
通过折半内存空间来避免出现内存碎片
标记整理算法
内存变动频繁,需要整理所有存活对象的内存地址
分代收集算法
将堆空间分为新生代和老年代,新生代又分为一个比较大的Eden区和两个比较小的survivor区。
两个survivor区起的就是一个缓冲的作用。
新生代98%的对象朝生夕死,采用复制算法。
老年代采用标记-整理算法。
何时回收
常见的垃圾收集器: