繁体   English   中英

了解JVM GC

[英]Understanding JVM GC

我试图了解下面的代码如何工作和输出。

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()调用, rt.gc()释放更多写在输出语句中的内存(> 100 MB)。 我如何理解Java运行时的这种行为?

我不确定您要尝试什么。

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

另外,您在for循环中放入列表中的整数不符合垃圾回收的条件,因为它们是活动对象(即列表)的引用。 不确定什么是垃圾回收,因为我看不到程序的其余部分,但是您应该以某种方式修改测试,以使在垃圾回收时您拥有的对象不是活动对象所引用的。

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

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

似乎您获得的memoryFreed更少,因为它被用于rt.gc()调用的垃圾收集器活动。 实际上rt.gc()不会释放为您的数组分配的内存。 如果要查看GC释放了多少内存,则应在getRunTimeMemoryConsumption()方法外部进行计数,或者在测量之前将数组分配为null。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM