【问题标题】:Java still uses system memory after deallocation of objects and garbage collectionJava 在对象释放和垃圾回收后仍然使用系统内存
【发布时间】:2010-09-24 09:09:13
【问题描述】:

我正在运行 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();
}

}

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

【问题讨论】:

  • 那个操作系统有一个虚拟内存系统。 JVM 不保留物理内存。我猜你的意思是,为什么 JVM 不限制它使用的虚拟地址范围。

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


【解决方案1】:

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

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

【讨论】:

  • 我在这里澄清一下。在上面的特定测试用例中,调用 System.gc 将释放一些内存,即使注释列表不清晰且为空。这里列表是活动的,所以冻结了哪些内存
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-06-20
        • 2014-08-14
        • 1970-01-01
        • 1970-01-01
        • 2019-05-15
        • 2015-11-16
        • 1970-01-01
        相关资源
        最近更新 更多