java中方法的局部变量是放在虚拟机栈的局部变量表里面:
public static void main(String[] args) {
byte[] waste = new byte[6 * 1024 * 1024];
int new_var = 0;
System.gc();
}
上面的代码反编译后得到:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=3, args_size=1
0: ldc #2 // int 6291456
2: newarray byte
4: astore_1
5: iconst_0
6: istore_2
7: invokestatic #3 // Method java/lang/System.gc:()V
10: return
LineNumberTable:
line 3: 0
line 4: 5
line 5: 7
line 6: 10
可以看到locals=3,也就是说局部变量表长度是3,有man函数的参数,waste变量和new_var三个变量。
在JVM参数:-verbose:gc -Xmx12m -Xms12m 下GC日志:
[GC 6514K->6448K(11776K), 0.0011241 secs]
[Full GC 6448K->6356K(11776K), 0.0070312 secs]
这个看起来很正常,局部变量表引用了waste和new_var,所以他们的内存没有被释放。
我的疑问是,在执行System.gc()之前,waste变量的作用范围已经过期了,从int new_var = 0开始,后面就再也没有用到waste,那gc为什么不能回收waste的空间(虽然局部变量表保存了waste的引用)。