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

我正在运行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 list = new ArrayList(); /* 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永远不会将内存返回给操作系统。 是否这样做是特定于实现的。 对于那些不这样做的人,通常通过-Xmx标志启动时指定的内存限制是为其他应用程序保留内存的主要方法。

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

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

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

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

  • Sun Java System Application Server企业版8.1 2005Q1性能调优指南,第4章
  • 由Pete Freitag 调整垃圾收集大纲

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

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

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