这是我几个月来一直试图寻找的问题。我有一个正在运行的Java应用程序,该应用程序处理xml提要并将结果存储在数据库中。存在间歇性的资源问题,很难追踪。
背景: 在生产包装盒(问题最明显的地方)上,我对包装盒的访问不是特别好,并且无法使Jprofiler运行。那个盒子是运行centos 5.2,tomcat6和java 1.6.0.11的64位四核8gb机器。它以这些java-opts开头
JAVA_OPTS="-server -Xmx5g -Xms4g -Xss256k -XX:MaxPermSize=256m -XX:+PrintGCDetails -
XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC -XX:+PrintTenuringDistribution -XX:+UseParNewGC"
技术堆栈如下:
- Centos 64位5.2
- Java 6u11
- 雄猫6
- Spring / WebMVC 2.5
- 休眠3
- 石英1.6.1
- DBCP 1.2.1
- 的MySQL 5.0.45
- 高速缓存1.5.0
- (当然还有许多其他依赖项,特别是jakarta-commons库)
我最能重现该问题的是内存需求较低的32位计算机。我确实可以控制。我已经使用JProfiler对其进行了探究,并修复了许多性能问题(同步问题,预编译/缓存xpath查询,减少线程池,删除不必要的休眠预取以及处理过程中过度的“缓存变暖”)。
在每种情况下,探查器都显示这些资源由于某种原因占用了大量资源,并且一旦进行更改,这些资源就不再是主要的资源消耗。
问题: JVM似乎完全忽略了内存使用设置,填满了所有内存并且变得无响应。这对于面对最终客户的客户来说是个问题,他们希望定期进行轮询(每5分钟一次,然后重试1分钟),对于我们的运营团队来说,这是不断得到通知的,盒子已变得没有响应,必须重新启动它。此框上没有其他可运行的东西。
问题似乎是垃圾回收。我们使用ConcurrentMarkSweep(如上所述)收集器是因为原始的STW收集器导致JDBC超时并变得越来越慢。日志显示,随着内存使用量的增加,即开始引发cms故障,并踢回原始的世界停止收集器,然后该收集器似乎未正确收集。
但是,使用jprofiler运行时,“运行GC”按钮似乎可以很好地清理内存,而不是显示增加的占用空间,但是由于我无法将jprofiler直接连接到生产盒,并且无法解决已证明的热点问题,因此我正在使用剩下的是将Garbage Collection调为盲人的巫毒教。
我试过的
- 分析和修复热点。
- 使用STW,Parallel和CMS垃圾收集器。
- 以最小/最大堆大小以1 / 2、2 / 4、4 / 5、6 / 6增量运行。
- 以256M的permgen空间运行时,最大增量为1Gb。
- 以上的许多组合。
- 我还参考了JVM [调整参考](http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html),但实际上找不到解释此行为的任何信息或_which_调整的任何示例在这种情况下使用的参数。
- 我也(未成功)在脱机模式下尝试了jprofiler,并与jconsole,visualvm连接,但是我似乎找不到能影响我的gc日志数据的任何东西。
不幸的是,该问题还偶尔出现,它似乎是无法预测的,它可以运行几天甚至一周,而不会出现任何问题,或者一天可能失败40次,而我唯一能持续发现的问题就是垃圾收集正在起作用。
任何人都可以给予任何意见,以:
一)为什么一个JVM使用8场物理音乐会和2 GB的交换空间时,它被配置为最大出在小于6
b)至GC调谐的引用实际上解释或给出合理的例子与高级集合一起使用的时间和设置类型。
c)对最常见的Java内存泄漏的引用(我理解无人认领的引用,但我的意思是在库/框架级别,或者数据结构中更inherenet的内容,例如哈希映射)。
感谢您提供的所有见解。
编辑
Emil H:
1)是的,我的开发集群是生产数据的镜像,一直到媒体服务器。主要区别在于32/64位和可用的RAM数量,我无法轻松复制它们,但是代码,查询和设置是相同的。
2)有些旧代码依赖于JaxB,但是在重新排序作业以避免调度冲突时,由于每天运行一次,因此通常消除了执行。主解析器使用XPath查询,这些查询调用java.xml.xpath包。这是一些热点的源头,其中一个查询未预先编译,而两个查询的引用位于硬编码字符串中。我创建了一个线程安全的缓存(hashmap),并将对xpath查询的引用分解为最终的静态字符串,从而显着降低了资源消耗。查询仍然是处理的很大一部分,但这应该是因为这是应用程序的主要职责。
3)另外,另一个主要使用者是来自JAI的图像操作(重新处理来自提要的图像)。我对Java的图形库不熟悉,但是从我发现它们并不是特别泄漏。
(感谢您到目前为止的回答,伙计们!)
更新:
我能够使用VisualVM连接到生产实例,但是它禁用了GC可视化/ run-GC选项(尽管我可以在本地查看它)。有趣的是:VM的堆分配遵循JAVA_OPTS,并且实际分配的堆处于1-1.5 gigs的舒适水平,并且似乎没有泄漏,但是盒级监视仍然显示泄漏模式,但是未反映在VM监控中。这个盒子上没有其他东西在运行,所以我很困惑。