java - 如何调试JBoss或PostgreSQL内存不足的问题?

标签 java java-ee jboss

我正在尝试调试JBoss内存不足的问题。当JBoss启动并运行一段时间后,似乎使用了启动配置所期望的内存。但是,似乎只有JBoss正在使用唯一的Web应用程序执行某些未知的用户操作(或日志文件增长到一定大小)时,内存急剧增加,并且JBoss冻结。当JBoss冻结时,由于内存不足,很难终止进程或执行任何操作。

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

这是有关JBoss配置的信息:
JBoss(MX MicroKernel)4.0.3
JDK 1.6.0更新22
烫发大小= 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.1克
RES(住户尺寸):15克
CPU百分比:111.3%
%MEM:97.6%

在同一示例中,报告9分钟后,JBoss进程具有以下统计信息:
VIRT(总虚拟内存):39.1g
RES(住户尺寸):17克
CPU百分比:415.6%
%MEM:98.4%

用SIGKILL信号(-9)杀死JBoss进程后,新的JBoss进程据报告具有类似于以下内容的统计信息:
VIRT(总虚拟内存):7147m
RES(住户尺寸):1.3克
CPU百分比:11.6%
%MEM:7.3%

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

另外,在启动JVM时,我们将JVM选项设置为-XX:+ HeapDumpOnOutOfMemoryError -XX:HeapDumpPath = / path / to / dump,但是在发生内存问题时似乎没有写入任何路径。

建议使用以下其他选项:
[1]使用pmap生成进程地址空间的列表并查找大块(特别是名称为[anon]的大块)
[2]连续多次将SIGQUIT(kill -QUIT)发送到进程,并查找常见的堆栈跟踪
[3]使用jstack通过诸如jstack> tdump.out之类的命令获取线程转储。
[4]弄乱JBoss随附的JBoss管理工具/控制台,并查看随着事物开始消耗内存而留下什么样的对象
[5]探索Nagios作为另一种监控解决方案

以下是一些后续问题:
*从以上最重要的报告信息中,对这个问题是否有任何新的见解或想法?
*对于上述选项1-5,在问题造成的内存极低的情况下,最可能使用哪些选项?
*对于上述选项1-5,在问题允许诊断的非常短的时间范围内(例如1-3分钟),最可能使用哪些选项?
*有没有一种方法可以在特定进程的内存使用达到几个特定百分比阈值时自动将时间戳记写入文本文件,以便在查看JBoss日志文件时可以使用此时间戳记?
*当特定进程的内存使用量达到几个特定的​​百分比阈值时,是否有一种方法可以自动发送带有时间戳的电子邮件,从而可以使我们开始更加集中的监视?

最佳答案

在执行此基本过程之前,我已经解决了这些类型的问题:


在启动JVM时设置JVM选项-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps
运行该应用程序,等待失败(或导致失败),收集转储(.hprof文件)
查看Eclipse Memory Analyzer (MAT)中的转储,其中有一个不错的“泄漏可疑报告”
该报告希望说出类似“ XYZ类的82,302个实例正在占据74%的堆空间”之类的信息,然后您可以在需要更多信息时检查其中一些对象。


希望至少足以将您指出正确的方向以找到泄漏。

调试愉快!

关于java - 如何调试JBoss或PostgreSQL内存不足的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4588202/

相关文章:

java - JBoss MQ教程

authentication - Keycloak 将自定义属性检索到 KeycloakPrincipal

web-applications - JBoss Seam教程

java - 如何使用Java反射设置接口(interface)字段

java - 是否有一个 Java 库可以将 Olsen 时区 id 转换为 Windows 时区 id

java - 如何在oracle上使用wso2连接池避免非 Activity session ?

java - 为什么我的 JVM 的总内存使用量比它的 Xmx 值大 30 多倍?

java - 如何使用JSP/Servlet将文件上传到服务器?

java - Java 中的哈希表和同步