0

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

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 运行时的这种行为?

4

4 回答 4

2

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

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

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

于 2013-02-20T09:10:07.537 回答
2

你应该只比较rt.freeMemory()before 和 after rt.gc()。您的表达式会打印已使用的内存。这就是为什么这些值与您期望的相反。

于 2013-02-20T09:13:01.900 回答
0

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

于 2013-02-20T09:05:45.707 回答
0

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

于 2013-02-20T09:13:38.433 回答