我正在使用以下命令行选项启动一个JBoss 4.2服务器实例:
-Xms8192m -Xmx8192m -XX:+DisableExplicitGC -XX:MaxPermSize=512m
我还没有收到OutOfMemoryException,但我不认为内存使用量会随着引用的消亡而被GC。驻留内存使用量(使用top测量)从大约4.2G开始,在接下来的几天到一周内稳步增加,直到达到8.4G。我仍然没有收到异常。我担心的是,在重要活动期间(JBoss消息处理> 10k消息/秒),会有大约100-700ms的处理延迟,每隔6-10秒发生一次。这似乎也与驻留内存使用量的增加相关。这发生在一台拥有2个四核处理器和32G内存的机器上。
我将启用其他命令行参数:
-verbosegc -XX:+PrintGCDetails
但是,我想知道这似乎是垃圾收集问题,还是内存泄漏?几个星期以来,我一直试图追踪一个潜在的内存泄漏,并发现了一些我认为肯定可以解决的XML处理问题,但这是个死胡同。无论是否存在泄漏(尤其是在禁用显式GC的情况下),驻留内存使用量是否会攀升以满足Xmx的值?如果确实不是泄漏,是否有其他一些垃圾收集参数可能会有所帮助(例如修改垃圾收集器类型、存活者比率或暂停目标)?
我知道100-700ms的延迟似乎不是很多,但它有可能在这个应用程序中产生显着的不同。提前感谢您能提供的任何帮助/建议。
发布于 2011-10-05 05:20:07
Java中“泄漏”的定义与C/C++中的“泄漏”定义有很大的不同。在C/C++中,当你malloc或new一块存储,而不是随后free或delete它时,你会得到一个“泄漏”。
当然,在Java中,您永远不会删除任何内容,而是让GC来查找不再引用的内容并将其释放。
然而,可能发生的情况是,一些复杂的数据结构被构建起来,然后又构建了更多,然后又构建了更多,有时是无意的。
最明显的情况是像StringBuffer这样的东西,它用于累积日志信息,并且从不写入/清空。但是你也可以在你的应用程序中有一个(有意的)长生命结构,在这个结构中,你碰巧“驻留”了一些(假设)短生命的对象,但是在你处理完它之后,却没有将指针null到这个“短生命”对象,导致它实际上变成了不朽的对象。这些事情有些是显而易见的,有些则需要大量的调查才能弄清楚。
但在大型服务器中,即使没有这样的泄漏,在一段时间内也往往会有相当稳定的“东西”积累。例如,如果给定的应用程序被调用,它可能会导致创建一些对象(或者只是加载类,以及它们间接创建的对象),这些对象可能会“挂起”,直到下一次调用应用程序。像网页缓存这样的东西会被填满。如果使用类似JSP的东西,将为其创建对象并“缓存”以供以后使用。
但这种“物质”的积累应该观察到一种渐近行为,随着时间的推移慢慢接近某个稳态值。如果它在一个稳定的状态下继续上升,那么你可能确实有一个“泄漏”。
考虑到GC的行为,在繁忙的服务器上每隔几秒钟运行一次GC并不少见。您可以尝试使用调优参数来“平衡”不同的GC“层”,但这样做有点像是一门艺术。服务器上的GC性能通常很差,这仅仅是因为有一个没有为服务器设计良好的GC实现--繁忙服务器上的GC需要能够以主要并发的方式运行,而大多数GC实现并不能很好地做到这一点。
发布于 2011-10-05 06:09:02
我还没有收到OutOfMemoryException,但是我不认为内存使用量会增加,因为当它们的引用死亡时,会被GC掉。
这不一定是正确的。可以将对象放在堆的保留期内存中。如果对象被引用的时间超过“短时间”,就会发生这种情况。一旦进入保留期,它通常不会被垃圾收集,直到达到最大堆。因此,堆内存使用量没有减少并不意味着有泄漏。
正常的内存配置文件(堆使用量与时间)看起来像锯齿状-内存使用量缓慢增加,直到达到某个阈值(通常是最大堆),然后由于GC而减少,然后再次缓慢增加。
发布于 2011-10-05 06:40:22
我唯一要添加的就是尝试将一个分析器连接到您的应用程序,并查看内存使用情况。我已经用jProfiler和YourKit成功地分析了WebLogicA.S.的实例,尽管我还没有用JBoss尝试过,应该是相当简单的。
您是否可以在测试环境中复制此行为(因为分析器对性能的要求很高,所以只有在生产环境中才能在绝望的情况下这样做)?如果这样做,您可以查看GC是否仅在达到XMX阈值时才被调用(并不意味着有任何错误),并且您可以显式地调用GC来查看它的行为。即使使用GC调用,内存也会持续增加,这可能表明出现了问题。
一个好的分析器可以告诉你哪些对象在数量上增长得更快等等,如果你确实有一个“泄漏”,这可以给你很大的帮助。
https://stackoverflow.com/questions/7654015
复制相似问题