对于大型应用程序,Java 6 消耗的内存是否比您预期的要多?
我有一个多年来一直在开发的应用程序,到目前为止,在我的特定测试配置中占用了大约 30-40 MB;现在使用 Java 6u10 和 11,它在 Activity 时需要数百个。它反弹很多,介于 50M 和 200M 之间,当它空闲时,它执行 GC 并立即丢弃内存。此外,它还会产生数百万个页面错误。所有这些都通过 Windows 任务管理器进行观察。
所以,我在我的分析器 (jProfiler) 下运行它并使用 jVisualVM,它们都表明通常的中等堆和 perm-gen 使用量合计约为 30M,即使在我的负载测试周期完全活跃时也是如此。
所以我很困惑!而且它不只是从 Windows 虚拟内存池请求更多内存 - 这显示为 200M“内存使用情况”。
澄清:我想非常清楚这一点 - 在 18 小时内使用 Java VisualVM 观察到,类堆和 perm gen 堆非常稳定。分配的 volatile 堆(eden 和tenured)保持不动,为 16MB(它在最初的几分钟内达到),并且此内存的使用以完美的模式波动,从 8MB 均匀增长到 16MB,此时 GC 启动将其降回 8MB。在这 18 小时内,系统处于恒定的最大负载下,因为我正在运行压力测试。这种行为是完美并且始终可重现的,在多次运行中都可以看到。唯一的异常是,当这发生时,从 Windows 获取的内存,通过任务管理器观察到,从 64MB 到 900+MB 到处波动。
2008-12-18 更新:我已经使用 -Xms16M -Xmx16M 运行程序,没有任何明显的不利影响 - 性能很好,总运行时间大致相同。但内存使用在短期内仍达到 180M 左右的峰值。
2009-01-21 更新:似乎答案可能在于线程数 - 请参阅下面的答案。
编辑:我的意思是字面上的数百万个页面错误 - 在 30M+ 的区域内。
编辑:我有一台 4G 机器,所以 200M 在这方面并不重要。
最佳答案
针对 Ran 的回答的评论中的讨论,这里有一个测试用例,证明 JVM 在某些情况下会将内存释放回操作系统:
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 调整确切的行为-- 该页面上的一些选项也可能有助于回答原始问题。
关于Java 6 内存使用过多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/366658/