4

我们正在使用 IBM JDK 1.4.2 在 AIX 上的 Websphere Portal Server 5.1 上将一个相当复杂的应用程序作为 portlet 运行。在我们的生产系统上,我可以在详细的 GC 日志中看到一个奇怪的行为。在一段时间的正常行为之后,系统可以开始快速分配越来越大的块。系统开始花费超过 1000 毫秒来完成每个 GC,但是分配块的速度非常快,以至于分配失败之间只有 30 毫秒的间隔。

  • 每个分配失败比最后一个稍大一些整数 x 1024 字节。例如,您可能有 5 MB,然后不久之后 5 MB + 17 * 1024。
  • 这可以持续长达 10 分钟。
  • 在停止之前,这些块的大小往往会增长到 8 到 14 MB。
  • 这是一个四核系统,我假设它现在花费超过 95% 的时间进行 GC,其中三个核心等待另一个核心完成 GC。10 分钟。哎哟。
  • 显然,此时系统性能会下降。
  • 我们有 JSF、hibernate 和 JDBC、Web 服务调用、log4j 输出等等。

我认为这可能是基础设施而不是我们的应用程序代码。如果是循环内的错误字符串连接,我们预计会比 1024 个块有更多的不规则增长。如果是 StringBuffer 或 ArrayList 增长,我们会看到块大小翻倍。这种增长让我想到了日志缓冲或其他东西。在我们的应用程序中我想不出任何分配甚至 1 MB 的东西,更不用说 14。今天我在内存中寻找日志记录备份,然后再刷新到磁盘,但是在这段 GC 颠簸期间的日志记录语句量远不及MB 范围。

很明显,问题在于过多的内存分配,而不是垃圾收集,垃圾收集只是尽力跟上。有些东西正在分配一个大块并试图以太小的增量低效地增长它。

当系统处于负载状态时,有什么想法可能导致所有这些吗?有人看到与 Portal Server 类似的东西吗?

注意:对于任何感兴趣的人来说,原因似乎是偶尔但巨大的数据库查询。罪魁祸首似乎是 Hibernate 或 JDBC 驱动程序。

4

3 回答 3

2

不确定是什么导致了问题,但这里有一个关于如何进行更多调查的想法:IBM JDK 很棒,因为它可以配置为在收到 SIGQUIT 信号时进行堆转储。
在之前的项目中,它不是我们的 JDK,但只要我们有内存问题需要调查,我们就会使用它。

以下是启用堆转储的方法:http: //publib.boulder.ibm.com/infocenter/javasdk/v1r4m2/index.jsp ?topic=/com.ibm.java.doc.diagnostics.142j9/html/enabling_a_heapdump.html

然后有一个名为 heaproot 的工具,可以让您查看这些转储中的内容。

找到对象的类型应该会让你找到罪魁祸首。

于 2009-04-03T09:43:38.613 回答
1

根据您使用的 IBM JDK 的确切版本,有多种用于跟踪“大分配”的选项。区别主要在于实现,结果是当分配超过一定大小时记录 Java 堆栈跟踪(这应该有助于您追查罪魁祸首)。

“主权”1.4.2 SR4+: http ://www-01.ibm.com/support/docview.wss?uid=swg21236523

“J9” 1.4.2(如果 Java 在 -Xj9 选项下运行):您需要获取 JVMPI / JVMTI 代理以实现相同目的,我现在找不到此链接。

于 2009-05-24T00:17:22.723 回答
0

只是一个提示......一旦我们有一个项目由于堆碎片而遭受主要的 GC 问题(Websphere 和 IBM JDK)。最后,我们添加了一个 JDK 开关来强制堆压缩。

Sun JDK 不倾向于有碎片堆,但 IBM JDK 由于不同的内存/GC 处理方式而存在。

试一试...我不记得魔法开关了。

于 2009-04-03T10:00:10.697 回答