了解JVM GC

时间:2013-02-20 08:56:54

标签: java performance garbage-collection jvm

我想了解下面编写的代码如何工作和输出。

public static void getRunTimeMemoryConsumption(){

List<Integer> array = new ArrayList<Integer>();
for(int i = 0 ; i < 100000 ; i++){
    array.add(i);
}

List<Integer> array1 = new ArrayList<Integer>();
for(int i = 0 ; i < 100 ; i++){
    array1.add(i);
}

Runtime rt = Runtime.getRuntime();

//Run the GC
rt.gc();

long memoryFreed = rt.totalMemory() - rt.freeMemory();
System.out.println("Memory freed in Mbytes :: " + memoryFreed/(1024));

}

当我运行此代码时,它总是给我132 KB作为输出(9/10运行)。 但是,如果我删除rt.gc()调用,我会在输出语句中写入更多内存释放(> 100 MB)。我如何理解Java Runtime的这种行为?

4 个答案:

答案 0 :(得分:2)

我不完全确定你在尝试什么。

您没有计算释放了多少内存,而是计算rt.totalMemory() - rt.freeMemory(),即使用了多少内存。考虑到这一点,你得到的结果很有意义,没有垃圾收集,然后在gc之后使用更多的内存。要了解释放了多少内存,您应该在调用垃圾收集器之前和之后比较rt.totalMemory() - rt.freeMemory()

您放入for循环列表中的整数也不符合垃圾收集的条件,因为它们是活动对象(即列表)的引用。不知道什么是垃圾收集,因为我没有看到你的程序的其余部分,但你应该修改你的测试,在垃圾收集点你有对象不是活动对象的引用。

答案 1 :(得分:2)

您应该在rt.freeMemory()之前和之后比较rt.gc()。表达式打印已用内存。这就是为什么这些价值与你期望的相反。

答案 2 :(得分:0)

这里的垃圾收集不会真正删除任何东西,因为你没有任何超出范围的对象。该方法对两个列表进行了范围调整,因此在垃圾回收调用之后它们仍可访问。垃圾收集通常是java中的计划任务,因此它可以在理论上随时运行。这意味着这里的行为实际上是好的,因为你不希望垃圾收集破坏仍然在范围内的对象(就像你在这里)。

答案 3 :(得分:0)

看起来你的内存较少,因为它花在了rt.gc()调用的垃圾收集器活动上。实际上rt.gc()不会释放为数组分配的内存。如果你想看看GC释放了多少内存,你应该在getRunTimeMemoryConsumption()方法之外进行计数,或者在测量之前将数组赋值为null。