9

我正在运行 JVM 1.5.0(Mac OS X 默认),并且正在活动监视器中监视我的 Java 程序。我有以下内容:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;

public class MemoryTest {

public static void memoryUsage() {
 System.out.println(
     Runtime.getRuntime().totalMemory() - 
     Runtime.getRuntime().freeMemory()
 );
}

public static void main( String[] args ) throws IOException {

    /* create a list */
    ArrayList<Date> list = new ArrayList<Date>();

    /* fill it with lots of data */
    for ( int i = 0; i < 5000000; i++ ) {
        list.add( new Date() );
    } // systems shows ~164 MB of physical being used

    /* clear it */
    memoryUsage();      //  about 154 MB
    list.clear();
    list = null;
    System.gc();
    memoryUsage();      //  about 151 KB, garbage collector worked

    // system still shows 164 MB of physical being used.
    System.out.println("Press enter to end...");
    BufferedReader br = new BufferedReader( 
            new InputStreamReader( System.in )
            );
    br.readLine();
}

}

那么为什么即使垃圾收集器似乎工作得很好,物理内存也没有被释放呢?

4

4 回答 4

19

许多 JVM 从不将内存返回给操作系统。是否这样做是特定于实现的。对于那些不这样做的人,在启动时指定的内存限制(通常通过 -Xmx 标志)是为其他应用程序保留内存的主要方法。

我很难找到关于这个主题的文档,但是Sun 的 Java 5 的垃圾收集器文档确实解决了这个问题,这表明在正确的条件下,如果使用正确的收集器,堆将会缩小——默认情况下,如果超过 70 % 的堆是空闲的,它会收缩到只有 40% 是空闲的。控制这些的命令行选项是-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio

于 2008-11-27T19:16:01.903 回答
5

JVM 有几个命令行选项可以帮助调整 Java 使用的堆大小。每个人都知道(或应该知道) -Xms 和 -Xmx,它们设置了堆的最小和最大大小。

但是还有 -XX:MinHeapFreeRatio 和 -XX:MaxHeapFreeRatio 是 JVM 管理可用空间的各自限制。它通过缩小使用的堆来做到这一点,并且可以降低程序的内存消耗。

您可以在这里找到更多信息:

于 2008-11-27T19:39:19.283 回答
3

您需要使用特定于 JVM 的分析器来监视程序使用的实际堆空间,而不是分配给 JVM 的内存。

JVM 不仅不愿意释放它分配的堆内存,而且由于各种原因(包括即时编译)而倾向于吞噬空间。

于 2008-11-27T19:27:45.297 回答
0

操作系统是否可能显示当前分配给程序的内存 - 即使分配了 150~ MB 也不意味着 150~ MB 正在使用中。

于 2008-11-27T19:16:51.463 回答