垃圾收集算法
- 在Java内存中,不停的有对象的创建与消亡,在内存一定的情况下,内存的动态分配和垃圾收集都由JVM去帮我们程序员自动完成,那么,JVM在内存回收时的疑问如下
哪些内存需要被回收
什么时候回收
如何回收
- 对象已经死了吗?
java对象几乎全部存放在堆中,垃圾收集的主要区域也是Java堆内存。在垃圾收集器进行垃圾收集时,首先要确定哪些对象还存活,不需要回收,哪些对象已经死去,需要被回收。
- 引用计数算法
给每个对象一个引用计数器,每当有一个地方引用它时,计数器的值就加一,当引用失效时,计数器的值就减1,任何时刻计数器的值为0的对象,代表不可能在被利用。
引用计数器的优缺点
- 实现简单,判断效率高
- 难以解决对象之间相互引用的问题
package com.schoki.jvm.chapter2;
/**
* @author : jzb219@gmial.com
* @description : 测试 objA objB是否会被回收
* @date : 2018/7/18 下午3:42
*/
public class ReferenceCountingGC {
public Object instance = null;
private static final int _1M = 1024 * 1024;
/**
* 该变量的意义在于占点内存,以便在垃圾收集时,可以看到GC日志中,是否会回收
*/
private byte[] bigSize = new byte[2 * _1M];
public static void main(String[] args) {
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
//假设发生GC, objA objB是否会被回收
System.gc();
}
}
运行结果(JDK1.8)
[GC (System.gc()) [PSYoungGen: 6779K->576K(38400K)] 6779K->584K(125952K), 0.0016589 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 576K->0K(38400K)] [ParOldGen: 8K->509K(87552K)] 584K->509K(125952K), [Metaspace: 3286K->3286K(1056768K)], 0.0075244 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 38400K, used 333K [0x0000000795580000, 0x0000000798000000, 0x00000007c0000000)
eden space 33280K, 1% used [0x0000000795580000,0x00000007955d34a8,0x0000000797600000)
from space 5120K, 0% used [0x0000000797600000,0x0000000797600000,0x0000000797b00000)
to space 5120K, 0% used [0x0000000797b00000,0x0000000797b00000,0x0000000798000000)
ParOldGen total 87552K, used 509K [0x0000000740000000, 0x0000000745580000, 0x0000000795580000)
object space 87552K, 0% used [0x0000000740000000,0x000000074007f690,0x0000000745580000)
Metaspace used 3292K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 363K, capacity 388K, committed 512K, reserved 1048576K
从运行结果可以看到
- 第一行中PSYoungGen ,说明收集器采用的是Parallel Scavenge收集器
- 6779K->576K(38400K),回收前是6779K,回收后576K,说明虽然objA和objB存在相互引用,但是依然会被垃圾收集器回收掉,从侧面也说明垃圾收集算法采用的不是引用计数算法
- 可达性分析算法
通过一些列(注意是很多哦,我特么刚开始以为一个应用里面就一个GC Roots)的成为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(或者说GC Roots到这个对象不可达),则说明这个对象是不可用的
哪些对象可以作为GC Roots
- 虚拟机栈(栈帧中的本地变量表)中引用的对象--代表应用上下文
- 方法区中类静态属性引用的对象
- 方法区中,常量引用的对象
- 本地方法栈中JNI(一般说native方法)引用的对象(注:这个没太搞明白)
参考
周志明《深入理解Java虚拟机》
写在最后
做一个灵魂和肉体分离的人,灵魂不受肉体的束缚,灵魂可以指挥肉体
网友评论