我们有几个正在生产中运行数据服务的虚拟机,客户端向数据服务发送Restful HTTP请求,负载有点繁重(一般每个主机每秒500个请求),并且每个虚拟机上的负载总是平衡的。我们在所有主机上都有相同的配置(2个CPU,-Xms2048m -Xmx4096m -XX:MaxPermSize = 192m -XX:NewSize = 512m -XX:MaxNewSize = 512M -XX:+ UseConcMarkSweepGC -XX:+ CMSClassUnloadingEnabled -XX:+ HeapDumpOnOutOfMemoryError)< / p>
两天前,我们看到旧的生成堆使用量开始增长,其中5个虚拟机(每天300 MB),旧生成堆使用量保持不变(约80 MB),我们正在尝试识别根因为,请问这是内存泄漏问题还是只是正常情况?旧的内存使用量的增长是否总是意味着java中的内存泄漏?
感谢。
更新:我们昨天刚刚重新启动了这5台主机,所有这些旧机器堆的使用率都恢复正常,但是,在我们今天早上的峰值负载之后,其中一台机器上的旧生成堆使用率开始了再次成长......
答案 0 :(得分:4)
旧的内存使用量增长是否始终意味着java中的内存泄漏?
不一定。
并发标记清除垃圾收集器在收集期间不压缩旧的gen。因此,在足够的内存负载下,可能会产生大量碎片,从而无法回收足够的内存以便将终身对象升级到旧的gen空间。
尝试打开这些参数,看看发生了什么:
-XX:+ PrintGCDetails -XX:+ PrintPromotionFailure -XX:PrintFLSStatistics = 1
查找促销失败和频繁的完整GC扫描,无法释放大量内存。
如果您使用的是Java 7或更高版本,可以尝试切换到G1 collector(-XX:+ UseG1GC而不是-XX:+ UseConcMarkSweepGC)。这是一个紧凑的收集器,可以避免上述一些问题。
如果在此之后你仍然遇到问题,那么我会查看你的代码,看看是否有东西挂在对象引用上,不应该。
编辑:由于这种情况发生在某些主机而非其他主机上,我倾向于代码问题,可能与意外的用户输入有关,因为它只是偶尔发生。
答案 1 :(得分:0)
听起来你所描述的是内存泄漏。因为对我来说,内存泄漏是指您的内存在没有任何充分理由的情况下及时增加或没有开发人员理解原因。这可能意味着您实际上不需要的某些数据仍然可能由于错误而保留在内存中。
我会考虑使用一个好的分析器来找到根本原因。这可能是最简单的。我不知道我是否被允许在这里命名产品,但是JProfiler在我工作的多个项目中保存了我的团队。