我在 3 岁的 Solaris 系统上运行一个 J2EE 应用程序,使用的堆大约为 300 MB。从 gc 日志中我看到,每天触发几次的完整 gc 大约需要 5 秒,并且每次恢复大约 200 MB。一个完整的 gc 在这么小的堆上花费这么长时间的原因是什么?
我运行 java 1.6.0_37。
我在 3 岁的 Solaris 系统上运行一个 J2EE 应用程序,使用的堆大约为 300 MB。从 gc 日志中我看到,每天触发几次的完整 gc 大约需要 5 秒,并且每次恢复大约 200 MB。一个完整的 gc 在这么小的堆上花费这么长时间的原因是什么?
我运行 java 1.6.0_37。
缓慢的完整 GC(以及次要 GC)主要是由于硬件设置不佳,其次是软件配置(即 GC 人机工程学),最后是堆中的对象数量。
查看硬件,您在 Solaris 上使用的 CPU 型号和供应商是什么?它是具有多个内核的 SMP 系统吗?每个核心是否有多个线程?您的 GC 是否利用了系统上所有可用的虚拟处理器,即垃圾收集是否分布在多个处理器上?
另一种使完全 GC 执行缓慢的情况是,如果堆的一部分从主内存中换出。在这种情况下,必须在垃圾收集期间将换出的内存页面换入,这可能是一个相当耗时的过程。在这种情况下,您的机器上没有安装足够的物理内存。
系统上的任何其他应用程序是否竞争相同的物理资源,即 CPU 和内存?
看看 GC 人体工程学,您使用的是什么收集器?我会推荐使用多个收集器线程的并行吞吐量收集器或 G1 收集器。我还建议使用 NUMA 配置。
一些一般规则:
有关 GC 人体工程学的更多信息: http ://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html