总可用内存java

时间:2016-02-26 22:50:52

标签: java memory garbage-collection

我想知道为什么在创建大表后总可用内存不会发生变化。但是当我使用垃圾收集器时总的可用内存增加了。

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

2 个答案:

答案 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 ,但有很多可能的解释,包括:

  • 可能已加载了额外的类,导致堆使用量增加
  • 某些代码可能已被JIT编译,导致堆使用量增加
  • 对象可能已经分配在不经常收集的堆区域中。例如,可以将大型数组直接分配到终身空间......

总结:Java内存分配/垃圾收集很复杂......初学者最好不要使用简单(天真)的“黑盒子”测试来弄清楚它是如何工作的 2 。您将通过查找/阅读文章了解更多信息。

1 - 确切地说,GC 可能回收调用明确分配的所有内存...但是还有其他事情发生意味着这没有反映出来在“自由空间”中。

2 - 如果你的头部爆炸,它会在地毯上留下令人讨厌的污渍......: - )