垃圾回收 - 更改收集器算法

4
我们正在Tomcat上运行Spring+Hibernate Web应用程序(Java 1.5)。目前,我们使用2GB的堆空间(据我所知,在Solaris 32位服务器上这是最大可能的,尽管服务器有16GB的总内存)。当前的JAVA_OPTS如下:
-XX:MaxPermSize=512m -XX:+UseParallelGC -Xms2048m -Xmx2048m
年轻代+幸存者空间约为600 MB,老年代为1.4 GB。
有时候内存会满,我们需要重新启动Tomcat。以下是一些观察结果:
  1. 在服务器活跃运行了约16个小时后,GC花费了大约一个小时进行标记清除(~300次收集-老年代),并花费了5-7分钟进行Scavenging(~1500次收集-年轻代)。
  2. 有时候老年代在10分钟内就会被填满,我们需要重新启动服务器。目前尚未成功地找到引起问题的线程。
我们想要更改为以下JAVA_OPTIONS-我需要反馈是否明智的选择(UAT环境与Prod env的负载不匹配,我们无法在UAT中复制相同的负载):
  1. 添加-Xmn1024m-这是为了确保年轻代对象不容易晋升到老年代。增加/减少此值的建议是什么?这也将导致更多的年轻代GC和较少的老年代GC。

  2. -XX:+UseParallelOldGC-这是为了使年轻代和老年代GC运行多个线程,以便它们能够更快地进行GC。

  3. 2GB的限制是否适用于Solaris服务器?堆空间是否可以增加到超过2GB?

请分享您对上述内容的想法。
谢谢, Midhun

我认为找到潜在问题会更好。如果老年代在10分钟内就被填满(并且无法进行垃圾回收)...那么这显然是程序中的内存泄漏,通过调整JVM你不会解决任何问题。它只会在15分钟而不是10分钟内被填满。只需找到泄漏并修复即可。 - Radu Murzea
1
你尝试过在内存占满时获取内存转储并分析填充内存的对象吗?这样做可以提供有价值的提示,指出对象是在哪里创建/泄漏的。使用-XX:+HeapDumpOnOutOfMemoryError可以自动创建转储。 - Roger Lindsjö
1
现在考虑使用64位JVM是一个不错的选择,这样您就不会受到限制。同时升级到Java 6或7也是值得考虑的。这两种方法都将为您提供更多的选项。 - Peter Lawrey
@SoboLAN 我知道这里有个内存泄漏。但是由于有很多线程在运行,所以变得很难找到是哪个线程导致了泄漏。正如Roger建议的那样,我现在正在尝试使用jmap获取堆转储。我正在使用Eclipse MAT进行测试。希望这能帮助我们缩小到正确的线程。 - Midhun Agnihotram
@Peter - 我们将在不久的将来转向Java 6和64位VM。但我们正在寻找一个快速解决方案 :) - Midhun Agnihotram
@MidhunAgnihotram 你是如何得出这些观察结果的?你在运行任何监控程序吗?或者你使用类似 Visual Vm 的工具。 - AnirbanDebnath
1个回答

1

如果您遇到了过长的主要收集暂停时间,您应该考虑使用-XX:+UseConcMarkSweepGC(同时保持-XX:+UseParallelOldGC)以便并发执行垃圾回收。

如果您使用-Xms2048m -Xmx2048m,这可能是个坏主意,如果这些值不太好,您就不能让JVM自动调整它们(但如果您确定没有问题,也可以这样做)。 在《Java性能调优第二版》中,关于堆大小提出了5个常见建议:

  1. 将起始堆大小设置为最大堆大小相同
  2. 将起始大小设置为最大数量的活动对象所需的大小,并将最大值设置为此数量的4倍
  3. 将起始堆设置为最大堆大小
  4. 将起始堆大小设置为最大堆大小的1/10到1/4之间
  5. 使用默认初始堆大小

(尝试找到最适合您的方法)

这份文档提供了解决GC问题的好建议,请仔细阅读代大小调整段落,并尝试一些命令来打印您的GC活动,其中一些命令确实可以帮助您查看应用程序或GC配置中的瓶颈。


1
据我所读,-XX:+UseConcMarkSweepGC可以与-XX:+UseParNewGC一起使用,以便在并行收集年轻代和同时收集老年代。唯一让我担心的是,并发收集器不会压缩旧年代 - 我认为这可能更成问题。我们将Xmx和XMs更改为相同,以避免JVM的缩放时间。我读到说这对于像我们这样的大型JVM来说是一种很好的技术。 - Midhun Agnihotram
好的,看我的编辑。无论如何,调整JVM并不是一项显而易见的实践,因此您应该使用监控工具来测试使用不同命令对性能的影响。祝好运! - alain.janinm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接