JVM笔记四:垃圾收集器与内存分配策略——对象

文章目录
  1. 1. 引用计数法
  2. 2. 可达性分析算法
  3. 3. 再谈引用

在堆里存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还存活着,哪些已经死去(即不可能再被任何途径使用的对象)。

引用计数法

引用计数法(Reference Counting):给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减1;任何时刻计数器为0的对象是不可能被使用的。主流的Java虚拟机里没有使用引用计数法来管理内存,主要原因是它很难解决对象之间的相互循环引用的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 引用计数器算法的缺陷
* VM Args:-XX:+PrintGCDetails
* JDK1.6
* Created by larry.su on 2017/2/18.
*/

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();
}
}

运行结果:

1
2
3
4
5
6
7
8
[Full GC (System) [CMS: 0K->423K(63872K), 0.0099285 secs] **6167K->423K**(83008K), [CMS Perm : 4749K->4747K(21248K)], 0.0107293 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap
par new generation total 19136K, used 1021K [7f3000000, 7f44c0000, 7f44c0000)
eden space 17024K, 6% used [7f3000000, 7f30ff670, 7f40a0000)
from space 2112K, 0% used [7f40a0000, 7f40a0000, 7f42b0000)
to space 2112K, 0% used [7f42b0000, 7f42b0000, 7f44c0000)
concurrent mark-sweep generation total 63872K, used 423K [7f44c0000, 7f8320000, 7fae00000)
concurrent-mark-sweep perm gen total 21248K, used 4880K [7fae00000, 7fc2c0000, 800000000)

6167K->423K(83008K)意味着虚拟机并没有因为这两个对象并相互引用就不回收他们,也从侧面说明虚拟机并不是通过引用计数法来判断对象是否存活的。

可达性分析算法

可达性分析算法

再谈引用

在JDK1.2之后,Java对引用的概念进行了扩充,分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,这4种引用强度依次逐渐减弱

reference