我想了解下面编写的代码如何工作和输出。
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的这种行为?
答案 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。