我试图理解我的下面编写的代码是如何工作和输出的。
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的这种行为?
我不完全确定你在尝试什么。
你没有计算释放了多少内存,你正在计算rt.totalMemory() - rt.freeMemory()
,即使用了多少内存。考虑到这一点,你得到的结果很有意义,没有垃圾收集,然后在gc之后使用更多的内存。要了解释放了多少内存,您应该在调用垃圾收集器之前和之后比较rt.totalMemory() - rt.freeMemory()
。
您放在for循环中的列表中的整数也不符合垃圾回收的条件,因为它们是活动对象(即列表)的引用。不知道什么是垃圾收集,因为我没有看到你的程序的其余部分,但你应该修改你的测试,在垃圾收集点你有对象不是活动对象引用。
你应该只比较rt.freeMemory()
之前和之后的rt.gc()
。表达式打印已用内存。这就是为什么价值与您的预期相反的原因。
这里的垃圾收集不会真正删除任何东西,因为你没有任何超出范围的对象。该方法对两个列表进行了范围调整,因此在垃圾回收调用之后它们仍可访问。垃圾收集通常是java中的计划任务,因此它可以在理论上随时运行。这意味着这里的行为实际上是好的,因为你不希望垃圾收集破坏仍然在范围内的对象(就像你在这里)。
看起来你的内存少了,因为它花在了rt.gc()调用的垃圾收集器活动上。实际上rt.gc()不会释放为数组分配的内存。如果要查看GC释放了多少内存,则应在getRunTimeMemoryConsumption()方法之外进行计数,或者在测量之前将数组指定为null。