在释放对象和垃圾回收后,Java仍然使用系统内存

时间:2008-11-27 19:11:11

标签: java memory-management memory-leaks garbage-collection

我正在运行JVM 1.5.0(Mac OS X Default),我在Activity Monitor中监视我的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 个答案:

答案 0 :(得分:19)

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

我很难找到关于这个主题的文档,但是garbage collector documentation for Sun's Java 5确实解决了这个问题,建议在正确的条件下,如果使用了正确的收集器,堆将会收缩 - 默认情况下,如果更多, 70%的堆是免费的,它会缩小,因此只有40%是免费的。用于控制这些选项的命令行选项为-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio

答案 1 :(得分:5)

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

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

您可以在此处找到更多信息:

答案 2 :(得分:3)

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

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

答案 3 :(得分:0)

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