Java 如何调试JBoss或PostgreSQL内存不足问题?

Java 如何调试JBoss或PostgreSQL内存不足问题?,java,jakarta-ee,jboss,Java,Jakarta Ee,Jboss,我正在尝试调试JBoss的内存不足问题。当JBoss启动并运行一段时间时,它似乎按照启动配置的预期使用内存。然而,当使用JBoss提供的唯一web应用程序执行一些未知的用户操作(或者日志文件增长到一定大小)时,内存会急剧增加,JBoss会冻结。当JBoss冻结时,由于内存不足,很难终止进程或执行任何操作。 当进程最终通过-9参数终止并且服务器重新启动时,日志文件非常小,只包含新启动的进程启动时的输出,而不包含内存为什么增加这么多的任何信息。这就是调试如此困难的原因:server.log没有来自被

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

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

这是关于JBoss配置的信息:
JBoss(MX微内核)4.0.3
JDK 1.6.0更新22
PermSize=512m
MaxPermSize=512m
Xms=1024m
Xmx=6144m

这是系统的基本信息:
操作系统:CentOS Linux 5.5
内核和CPU:x86_64上的Linux 2.6.18-194.26.1.el5
处理器信息:英特尔(R)至强(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.38 GB,使用了2.46 GB
虚拟内存:总共19.59 GB,使用了0个字节
本地磁盘空间:总共113.37 GB,使用了11.89 GB

当JBoss冻结时,系统信息如下所示:
正在运行的进程:225
CPU平均负载:4.66(1分钟)1.84(5分钟)0.93(15分钟)
CPU使用率:0%用户,12%内核,73%IO,15%空闲
实际内存:总共17.38 GB,使用了17.18 GB
虚拟内存:总共19.59 GB,使用了706.29 MB
本地磁盘空间:总共113.37 GB,使用了11.89 GB

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

下面添加了此问题的更新 非常感谢您的评论。我们正在发布此问题的更新,可能会有所帮助

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

例如,当按内存排序时,JBoss进程有一次报告具有以下统计信息(请注意,实际内存总量为17.38 GB,JBoss只获得6 GB堆):
VIRT(总虚拟内存):23.1g
RES(驻留集大小):15g
%CPU:111.3%
%成员:97.6%

在同一个示例中,9分钟后JBoss进程报告有以下统计信息:
VIRT(总虚拟内存):39.1g
RES(驻留集大小):17g
%CPU:415.6%
%成员:98.4%

在使用SIGKILL信号(-9)终止JBoss进程之后,新的JBoss进程报告具有与以下类似的统计信息:
VIRT(总虚拟内存):7147m
RES(常驻集大小):1.3g
%CPU:11.6%
%成员:7.3%

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

此外,我们在启动JVM时设置JVM选项-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/path/to/dumps,但在内存问题发生时,似乎没有写入路径

建议了以下其他选项:
[1] 使用pmap生成进程地址空间列表,并查找大数据块(特别是名为[anon]的大数据块)
[2] 连续多次向进程发送SIGQUIT(kill-QUIT),并查找常见的堆栈跟踪
[3] 使用jstack命令获取线程转储,例如jstack>tdump.out
[4] 摆弄JBoss随附的JBoss管理工具/控制台,看看当东西开始消耗内存时,什么样的对象还挂在那里
[5] 探索Nagios作为另一个监控解决方案

下面是一些后续问题:
*从上述最重要的报告信息中,是否有关于该问题的新见解或想法?
*对于上述选项1-5,哪些选项最有可能在问题造成的极低内存环境下工作?
*对于上述选项1-5,哪些选项最有可能在故障允许诊断的极短时间内(例如1-3分钟)工作?
*当特定进程的内存使用达到几个特定的百分比阈值时,有没有一种方法可以自动向文本文件写入时间戳