我想知道为什么在创建大表后总可用内存不会发生变化。但是当我使用垃圾收集器时总的可用内存增加了。
import java.util.Random;
public class Main{
public static void main(String[] args) throws Exception
{
C c = new C();
System.out.println("Free memory: "+Runtime.getRuntime().freeMemory());
c.CreateTable();
System.out.println("Free memory: "+Runtime.getRuntime().freeMemory());
System.gc();
System.out.println("Free memory: "+Runtime.getRuntime().freeMemory());
}
}
class C{
public void createTable()
{
int[] ar = new int[70000];
Random r = new Random();
for(int i = 0; i<ar.length;i++)
{
ar[i]=r.nextInt(99);
}
}
}
答案 0 :(得分:2)
这是因为JVM在TLAB(线程局部分配缓冲区)中创建了int [] ar。让我用以下示例解释一下:
1)假设系统中的总内存为100个单位。
2)即使只运行了一行代码,当前线程已经创建了TLAB beofre。
3)TLAB的内存(比如10个单位)已从总内存中扣除,即(Runtime.freeMemory显示90个单位)
4)int [] ar在TLAB内部创建,因为TLAB具有可用空间。
5)创建int []后运行Runtime.freeMemory显示90个单位(因为它是在TLAB中创建的)。
6)现在开始做GC你会再看到100个单位
答案 1 :(得分:1)
我无法重现您声称正在发生的行为:
$ java Main
Free memory: 126206592
Free memory: 125535432
Free memory: 125943720
如您所见,调用createTable()
后可用内存减少,然后在调用System.gc()
后再次增加。
现在你没有得到所有已分配的内存 1 ,但有很多可能的解释,包括:
总结:Java内存分配/垃圾收集很复杂......初学者最好不要使用简单(天真)的“黑盒子”测试来弄清楚它是如何工作的 2 。您将通过查找/阅读文章了解更多信息。
1 - 确切地说,GC 可能回收调用明确分配的所有内存...但是还有其他事情发生意味着这没有反映出来在“自由空间”中。
2 - 如果你的头部爆炸,它会在地毯上留下令人讨厌的污渍......: - )