Java 6消耗的内存是否超过了大型应用程序所期望的?
我有一个已经开发了多年的应用程序,到目前为止,在我的特定测试配置中,该应用程序大约占用了30-40 MB。现在使用Java 6u10和11时, Activity 时需要花费数百美元。它反弹很多,在50M到200M之间的任何地方,当它空闲时,它将执行GC并立即降低内存。此外,它还会生成数百万个页面错误。所有这些都可以通过Windows Task Manager进行观察。
因此,我将其运行在分析器(jProfiler)下并使用jVisualVM,它们都指示通常的中等堆和perm-gen使用量约为30M,即使在我的负载测试周期中完全活跃时也是如此。
所以我很迷惑!而且,它不仅从Windows虚拟内存池中请求更多内存,而且还显示为200M“内存使用量”。
澄清:我想对此非常清楚-使用Java VisualVM在18个小时的时间内观察到,类堆和perm gen堆一直非常稳定。分配的 volatile 堆(eden和Tenured)保持不变,为16MB(在最初的几分钟内到达),并且此内存的使用以从8MB均匀增长到16MB的完美模式波动,这时GC启动将其降回8MB。在这18个小时内,自从我进行压力测试以来,系统一直处于恒定的最大负载下。从许多运行中可以看出,这种行为是完美且始终如一的可重复性。唯一的异常是,在进行此操作时,通过任务管理器观察到的Windows内存变化范围从64MB到900 + MB不等。
更新2008-12-18:我已经使用-Xms16M -Xmx16M运行了程序,而没有任何明显的不利影响-性能很好,总运行时间大致相同。但是短期内内存使用仍然达到约180M的峰值。
更新2009年1月21日:似乎答案可能是线程数-请参阅下面的答案。
编辑:我的意思是数以百万计的页面错误-在30M +左右。
编辑:我有一台4G机,所以200M在这方面并不重要。
最佳答案
作为对Ran答案的评论中的讨论的回应,以下是一个测试案例,该案例证明JVM在某些情况下会将内存释放回OS:
public class FreeTest
{
public static void main(String[] args) throws Exception
{
byte[][] blob = new byte[60][1024*1024];
for(int i=0; i<blob.length; i++)
{
Thread.sleep(500);
System.out.println("freeing block "+i);
blob[i] = null;
System.gc();
}
}
}
在Java 1.4和Java 6 JVM(来自Sun)上,当计数达到40左右时,我看到JVM进程的大小减小了。
您甚至可以使用-XX:MaxHeapFreeRatio and -XX:MinHeapFreeRatio options调整确切的行为-该页面上的某些选项也可能有助于回答原始问题。