一 代码
/**
* 手动 GC 来理解不可达对象的回收
* -XX:+PrintGCDetails
*/
public class LocalVarGC {
// 触发 Minor GC 没有回收对象,然后在触发 Full GC 将该对象存入old区
public void localvarGC1() {
byte[] buffer = new byte[10 * 1024 * 1024]; // 10MB
System.gc();
}
// 触发 YoungGC 的时候,已经被回收了
public void localvarGC2() {
byte[] buffer = new byte[10 * 1024 * 1024];
buffer = null;
System.gc();
}
// 不会被回收,因为它还存放在局部变量表索引为1的槽中
public void localvarGC3() {
{
byte[] buffer = new byte[10 * 1024 * 1024];
}
System.gc();
}
// 会被回收,因为它还存放在局部变量表索引为1的槽中,但是后面定义的 value 把这个槽给替换了
public void localvarGC4() {
{
byte[] buffer = new byte[10 * 1024 * 1024];
}
int value = 10;
System.gc();
}
// localvarGC5中的数组已经被回收
public void localvarGC5() {
localvarGC1();
System.gc();
}
public static void main(String[] args) {
LocalVarGC local = new LocalVarGC();
local.localvarGC1();
// local.localvarGC2();
// local.localvarGC3();
// local.localvarGC4();
// local.localvarGC5();
}
}
1 localvarGC1() 测试
[GC (System.gc()) [PSYoungGen: 13930K->840K(71680K)] 13930K->11088K(235520K), 0.0077022 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (System.gc()) [PSYoungGen: 840K->0K(71680K)] [ParOldGen: 10248K->10840K(163840K)] 11088K->10840K(235520K), [Metaspace: 3203K->3203K(1056768K)], 0.0078262 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
new byte[10 * 1024 * 1024] 没有回收。
说明:触发 Minor GC 没有回收对象,然后在触发 Full GC 将该对象存入 old 区。
2 localvarGC2() 测试
[GC (System.gc()) [PSYoungGen: 13930K->776K(71680K)] 13930K->784K(235520K), 0.0009854 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 776K->0K(71680K)] [ParOldGen: 8K->599K(163840K)] 784K->599K(235520K), [Metaspace: 3187K->3187K(1056768K)], 0.0048599 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
new byte[10 * 1024 * 1024] 被回收。
说明:触发 YoungGC 的时候,已经被回收了。
3 localvarGC3() 测试
[GC (System.gc()) [PSYoungGen: 13930K->776K(71680K)] 13930K->11024K(235520K), 0.0064986 secs] [Times: user=0.09 sys=0.00, real=0.01 secs]
[Full GC (System.gc()) [PSYoungGen: 776K->0K(71680K)] [ParOldGen: 10248K->10841K(163840K)] 11024K->10841K(235520K), [Metaspace: 3203K->3203K(1056768K)], 0.0078091 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
new byte[10 * 1024 * 1024] 没有回收。
说明:不会被回收,因为它还存放在局部变量表索引为1的槽中。
4 localvarGC4() 测试
[GC (System.gc()) [PSYoungGen: 13930K->712K(71680K)] 13930K->720K(235520K), 0.0025408 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 712K->0K(71680K)] [ParOldGen: 8K->600K(163840K)] 720K->600K(235520K), [Metaspace: 3193K->3193K(1056768K)], 0.0063685 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
new byte[10 * 1024 * 1024] 被回收。
说明:会被回收,因为它还存放在局部变量表索引为1的槽中,但是后面定义的 value 把这个槽给替换了。
5 localvarGC5() 测试
[GC (System.gc()) [PSYoungGen: 13930K->712K(71680K)] 13930K->10960K(235520K), 0.0074081 secs] [Times: user=0.03 sys=0.03, real=0.01 secs]
[Full GC (System.gc()) [PSYoungGen: 712K->0K(71680K)] [ParOldGen: 10248K->10838K(163840K)] 10960K->10838K(235520K), [Metaspace: 3184K->3184K(1056768K)], 0.0081957 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (System.gc()) [PSYoungGen: 0K->0K(71680K)] 10838K->10838K(235520K), 0.0003689 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 0K->0K(71680K)] [ParOldGen: 10838K->598K(163840K)] 10838K->598K(235520K), [Metaspace: 3184K->3184K(1056768K)], 0.0048605 secs] [Times: user=0.05 sys=0.01, real=0.00 secs]
说明:因为 localvarGC1 结束后,对应的方法栈就没有了,new byte[10 * 1024 * 1024] 就失去了引用。