我有JVM参数(JVM 1.8.20)
-Xmx40M -Xms40M -verbose:gc -XX:+PrintGCDetails
和代码:
public static void main(String[] args) {
byte[] memory = null;
int MB = 1024 * 1024;
int c = 0;
while(c++<10){
memory = new byte[(int) (10 * MB)];
}
}
每次迭代后都有GC:
[GC(分配失败)[DefNew:932K-> 472K(12288K),0.0010986秒] 932K-> 472K(39616K),0.0011674秒] [时间:用户= 0.00 sys = 0.00,实际= 0.00秒]
[GC(分配失败)[DefNew:10931K-> 472K(12288K),0.0053905秒] 10931K-> 10712K(39616K),0.0054285秒] [时间:用户= 0.00 sys = 0.00,实际= 0.01秒]
[GC(分配失败)[DefNew:10712K-> 472K(12288K),0.0057686秒] 20952K-> 20952K(39616K),0.0058082秒] [时间:用户= 0.01 sys = 0.00,实际= 0.00秒]
[GC(分配失败)[DefNew:10712K-> 10712K(12288K),0.0000173秒] [终身:20480K-> 10711K(27328K),0.0041701秒] 31192K-> 10711K(39616K),[Metaspace] :85K-> 85K(4480K)],0.0042462秒] [次:用户= 0.00 sys = 0.00,实际= 0.00秒]
[GC(分配失败)[DefNew:10240K-> 0K(12288K),0.0033846秒] 20951K-> 20951K(39616K),0.0034223秒] [时间:用户= 0.00 sys = 0.00,实际= 0.00秒]
[GC(分配失败)[DefNew:10240K-> 10240K (12288K),0.0000158 secs] [终身:20951K-> 10711K (27328K), 0.0040890秒] 31191K-> 10711K(39616K),[元空间:85K-> 85K(4480K)],0.0041566秒] [次:用户= 0.02 sys = 0.00,实际= 0.00秒]
[GC(分配失败)[DefNew:10240K-> 0K(12288K),0.0026607秒] 20951K-> 20951K(39616K),0.0026945秒] [时间:用户= 0.00 sys = 0.00,实际= 0.00秒]
[GC(分配失败)[DefNew:10240K-> 10240K (12288K),0.0000169 secs] [终身:20951K-> 10711K (27328K), 0.0039672 secs] 31191K-> 10711K(39616K),[Metaspace:85K-> 85K(4480K)],0.0040413 secs] [次:用户= 0.00 sys = 0.00,real = 0.00 secs]
[GC(分配失败)[DefNew:10240K-> 0K(12288K),0.0026438 secs] 20951K-&gt; 20951K (39616K),0.0026780 secs] [次:用户= 0.01 sys = 0.00,实际= 0.00秒]
[GC(分配失败)[DefNew:10240K-> 10240K (12288K),0.0000158 secs] [终身:20951K-> 10711K (27328K), 0.0037923秒] 31191K-> 10711K(39616K),[元空间:85K-> 85K(4480K)],0.0038584秒] [次:用户= 0.00 sys = 0.00,实际= 0.01秒]
查看GC日志,堆中总有20M占用。但是每次迭代后应该有10M的活动对象。
你能帮我理解为什么有20M被占用吗?
答案 0 :(得分:1)
我认为你误解了日志。大部分时间你都有10M的占用率,这就是你的基线 - 运行时空闲时使用的基线。偶尔我们会看到GC后仍保留一个数组(箭头后显示的条目大约为20000 K)。
您选择用粗体字强调的数字是运行特定GC算法的详细结果。唯一相关的数字是那些单独嵌套在方括号内的数字。
我还要指出,你的代码是这样的,即数组永远不会被保留,它在创建时就会变成垃圾。这是因为memory
是一个局部变量,你永远不会从中读取它。