JavaGC机制
主要完成三件事情:一、哪些内存需要回收。二、什么时候回收。三、如何回收。
引用计数法
在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就+1;当引用失效时,计数器的值就-1;任何时刻计数器的值为零的对象就是不可能再被使用。
可达性分析算法
通过一系列的“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程中所走的路径称为“引用链”,如果某个对象到GC Roots间没有任何引用链相连,就证明GC Roots到该对象不可达,该对象就不可能再被使用。
finalize()方法
一个对象宣告死亡,需要经过两次标记过程:第一次就是经过可达性算法分析没有引用链与GC Roots相连,该对象就会被第一次标记。然后就会经过一次筛选,筛选的条件就是该对象是否被执行过finalize()方法。如果已经执行过或者没有覆盖,就不用执行。否则就会队列里执行该方法,该方法是对象逃脱死亡的最后一次机会。在队列里就会进行第二次标记。对象就会在finalize()方法里面寻找重新与引用链上的任何一个对象建立关联,只要建立关联成功,就会被移除该队列,就会避免被收集器收集。
四种回收算法
- 分代收集
弱分代:朝生夕灭
强分代:会熬过多次的垃圾收集
新生代,老年代之分 - 标记-清除算法
经历“标记”和“清除”两个阶段。首先标记出所需要回收的对象,在标记完成后,统一回收掉所有被标记的对象。
缺点:会产生大量不连续的内存碎片。 - 标记-复制算法
将内存容量分成大小相等的两块,每次只使用其中的一块。当使用的一块内存使用完了,就将还活着的对象复制到另一块,然后就把已使用的空间给清理掉。
缺点:如果对象存活多,效率低。
8:1:1 - 标记-整理算法
标记过程一样,然后让所有存活的对象都向内存的一端移动,然后清理掉边界以外的内存。
移动缺点:暂停程序,分区影响吞吐量。
GC Roots对象
- 在虚拟机栈中引用的对象。比如:线程中被调用的方法堆栈中用到的参数、局部变量,临时变量。
- 方法区中类静态属性引用的对象。比如:Java类的引用类型静态变量。
- 方法区中常量的引用对象。比如:字符串常量池里的引用。
- Java虚拟机内部引用。比如:基本数据类型的Class对象,系统类加载器。
- 被同步锁持有的对象。