首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从内存问题中调试JBoss或PostgreSQL?

如何从内存问题中调试JBoss或PostgreSQL?
EN

Stack Overflow用户
提问于 2011-01-03 20:44:11
回答 3查看 2.7K关注 0票数 1

我正在尝试调试内存中的JBoss问题。当JBoss启动并运行一段时间时,它似乎按照启动配置的意图使用内存。但是,当使用唯一的web应用程序JBoss进行一些未知的用户操作(或者日志文件增长到一定大小)时,内存会急剧增加,JBoss会冻结。当JBoss冻结时,由于内存不足,很难终止进程或做任何事情。

当进程最终通过a-9参数终止并且服务器被重新启动时,日志文件非常小,只包含来自新启动进程的输出,而不包含任何关于为什么内存增加了这么多的信息。这就是为什么调试如此困难的原因: server.log没有来自终止进程的信息。日志被设置为2GB,新进程的日志文件只有大约300 Kb,尽管它在正常内存环境下增长正常。

这是关于JBoss配置的信息:

JBoss (MX MicroKernel) 4.0.3

JDK 1.6.0更新22

PermSize=512m

MaxPermSize=512m

Xms=1024m

Xmx=6144m

这是系统的基本信息:

操作系统: CentOS Linux5.5

内核和CPU: Linux2.6.18-194.26.1.el5在x86_64上

处理器信息: Intel(R) Xeon(R) CPU E5420 @ 2.50GHz,8个核心

这是jboss服务启动几分钟后正常预冻结状态下系统的良好示例信息:

正在运行的进程: 183

CPU平均负荷: 0.16 (1分钟) 0.06 (5分钟) 0.09 (15分钟)

CPU使用率: 0%用户,0%内核,1% IO,99%空闲

实际内存:17.38GB,2.46GB

虚拟内存: 19.59 GB总计,使用0字节

本地磁盘空间:总计113.37 GB,使用11.89GB

当JBoss冻结时,系统信息如下所示:

正在运行的进程: 225

CPU平均负载: 4.66 (1分钟) 1.84 (5分钟) 0.93 (15分钟)

CPU使用率: 0%用户,12%内核,73% IO,15%空闲

实际内存:17.38GB总容量,17.18GB使用

虚拟内存:19.59GB总容量,706.29 MB

本地磁盘空间:总计113.37 GB,使用11.89GB

===========================================================

此问题的更新如下所示

非常感谢您的评论。我们正在发布对这个问题的更新,这可能会有帮助。

在再出现3次内存问题时,使用unix实用程序似乎表明JBoss进程是消耗所有内存的进程。当问题发生时,它似乎很快就会发生。例如,在JBoss之后的一段时间内运行良好(例如。(几天),用户在某一时刻采取了一些神秘的行动,之后,内存消耗似乎需要1-3分钟才能上升到导致性能严重下降的水平,再过5-10分钟,这种退化就会变得严重(例如。很难通过ssh运行简单的bash命令)。当然,这种模式会因用户在web应用程序上所做的事情而有所不同。

例如,在按内存进行排序时,据报告JBoss进程有以下统计数据(请注意,实际内存为17.38GB,JBoss仅为6GB堆):

VIRT (总虚拟内存):23.1g

驻地设置尺寸: 15g

%CPU: 111.3%

MEM%:97.6%

在同一示例中,9分钟后,据报告JBoss流程具有以下统计信息:

VIRT (总虚拟内存):39.1g

驻地设置尺寸: 17g

%CPU: 415.6%

MEM%:98.4%

在使用SIGKILL信号(-9)终止JBoss进程之后,据报告,新的JBoss进程具有类似于以下统计信息的统计信息:

虚拟内存总数:7147 M

驻地设置大小: 1.3g

CPU百分比: 11.6%

MEM%:7.3%

现在我们知道是JBoss进程消耗了所有的内存,我们想知道它的去向。我们尝试过使用jmap命令,例如jmap -dump:file=/home/dump.txt 16054,但是这似乎会大大降低服务器的响应能力,在一段时间后似乎什么也不会发生(例如。提示符不返回)。我们猜测是因为可用内存太少,堆太大了,有些东西挂起了。

此外,我们在启动JVM时设置了JVM选项-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps,但是当内存问题发生时,似乎不会将任何东西写入路径。

还提出了这些其他备选办法:

使用pmap生成进程地址空间的列表,并查找大块(特别是具有名称anon的大块)。

2连续几次将SIGQUIT (杀死-QUIT)发送到进程,并查找常见的堆栈跟踪

3使用j堆栈获得一个线程转储,命令包括j堆栈> tdump.out

4混乱地处理JBoss管理工具/控制台,这些工具和控制台都包含在JBoss中,并查看当东西开始消耗内存时,会留下什么样的对象。

5探索Nagios作为另一种监视解决方案

以下是一些后续问题:

*根据上述报告的资料,对这个问题是否有新的见解或想法?

*对于上述选项1-5,在问题所造成的极低内存环境下,哪一个最有可能工作?

*对于上述备选方案1-5,它们最有可能在问题允许诊断的非常短的时间框架内工作(例如。1-3分钟)?

*当某个特定进程的内存使用达到几个特定百分比阈值时,是否有一种方法可以自动地将时间戳写入文本文件,以便在查看JBoss日志文件时可以使用此时间戳?

*是否有办法在某一特定进程的内存使用达到几个特定百分比阈值时,自动发送带有时间戳的电子邮件,以便我们能够开始更有针对性的监测?

EN

回答 3

Stack Overflow用户

发布于 2011-01-03 21:46:08

我曾经用这个基本过程解决过这些类型的问题:

  1. 启动JVM时设置JVM选项-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps
  2. 运行应用程序,等待失败(如果可能的话),收集转储(.hprof文件)
  3. 查看日食内存分析器(MAT)中的转储,其中有一个很好的“泄漏嫌疑人报告”
  4. 这份报告希望能说出“XYZ类的82,302个实例占用了74%的堆空间”,如果需要更多信息,您可以检查其中的一些对象。

希望这至少能给你指明正确的方向,找到你的漏洞。

调试愉快!

票数 2
EN

Stack Overflow用户

发布于 2011-01-03 22:09:16

这还不足以进行诊断。

但让我们从我们所拥有的开始吧。我不知道您正在使用什么来显示内存统计数据,但它显示您的系统内存消耗总量已经跃升了15 GB。这很奇怪,因为您只为JBoss提供了一个6 GB的堆。

因此,首先要做的是验证JBoss是实际问题。最简单的方法是使用top,按总虚拟内存(VIRT)或驻留集大小(RES)对其进行排序。若要更改排序字段,请键入大写"F“,然后在后面的屏幕中选择该字段。

如果是JBoss进程消耗了所有的内存,那么您就需要弄清楚它的去向。可能的情况包括:大内存映射的JARfiles、通过Java分配的堆外缓冲区和从本机模块分配的内存。由于您将从顶部获得进程ID,所以使用pmap生成进程地址空间的列表,并查找大块(特别是名为[anon]的大块)。

如果不清楚在何处分配内存,则始终可以向进程发送SIGQUIT (kill -QUIT),该进程将向stderr写入线程转储(这将转到控制台,或者--希望--到日志文件)。连续多次执行此操作,并查找常见的堆栈跟踪。

根据您的更新(显示JBoss进程的虚拟大小),我认为检查Java堆是浪费时间。虽然我认为JVM可能忽略了-Xmx选项,但这是极不可能的。

这意味着增长发生在非堆内存中。一些可能性:

  • 使用直接的ByteBuffer。如果您使用缓冲区来缓存数据库的结果,那么很可能您分配了太多的缓冲区。这将通过pmap诊断,寻找大型[anon]块。
  • 无控制的线程创建。每个线程为其线程堆栈需要一定的空间。我不认为这是问题所在,因为每个线程空间的数量很小(iirc,不足1MB);您必须创建成千上万个线程空间。您可以使用pmap、查找小型[anon]块或向JVM发送SIGQUIT来诊断这一点。
  • 在C堆上分配大量内存的本机代码。您可能可以使用pmap进行诊断,但第一步是检查依赖项,以确定是否存在本机库。如果存在,请使用gdb或等效的方法进行调试。

作为最后的评论:与其问什么在低内存条件下可能起作用,我建议只是尝试这些选项,看看什么起作用和什么不起作用。

票数 1
EN

Stack Overflow用户

发布于 2011-01-03 20:50:17

一种解决方案是在JBoss服务器上使用VisualVM (包括在最新的JDK中)的远程JMX。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4588202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档