我们有几个在生产环境中运行数据服务的VM,客户端向数据服务发送Restful HTTP请求,负载比较重(通常每主机每秒500个请求),并且每个VM上的负载始终保持平衡。我们在所有主机上都具有相同的配置(2个CPU,-Xms2048m -Xmx4096m -XX:MaxPermSize = 192m -XX:NewSize = 512m -XX:MaxNewSize = 512M -XX:+ UseConcMarkSweepGC -XX:+ CMSClassUnloadingEnabled -XX:+ HeapDumpOnOutOfMemoryError)
两天前,我们看到其中5台VM的旧发电堆使用量开始增长(每天300 MB),其他VM上的旧发电堆使用量保持不变(大约80 MB),我们正在尝试找出根本原因,可能是我问这是内存泄漏问题还是正常情况?老一代的内存使用率增长是否总是意味着Java中的内存泄漏?
谢谢。
更新:我们昨天刚刚重新启动了这5台主机,所有主机上的旧发电堆使用率都与其他主机恢复正常,但是,在今天早晨出现高峰负载之后,其中一台的旧发电堆使用率又开始增长。 ..
老一代的内存使用率增长是否总是意味着Java中的内存泄漏?
不必要。
并发标记清除垃圾收集器不会在收集过程中压缩旧的gen。因此,在足够的内存负载下,有可能获得大量的碎片,从而无法回收足够的内存以将占有权的对象提升为旧的一代空间。
尝试打开这些参数,看看发生了什么:
-XX:+ PrintGCDetails -XX:+ PrintPromotionFailure -XX:PrintFLSStatistics = 1
查找升级失败和频繁的完整GC扫描,这些释放无法释放大量内存。
如果您使用的是Java 7或更高版本,则可以尝试切换到G1收集器(-XX:+ UseG1GC而不是-XX:+ UseConcMarkSweepGC)。这是一个紧凑的收集器,可以避免上述一些问题。
如果在那之后您仍然遇到问题,那么我将查看您的代码以查看是否应该在对象引用上挂上某些内容。
编辑:由于这是在某些主机上发生的,而不是在其他主机上发生的,我倾向于代码问题,可能与用户意外输入有关,因为它只是偶尔发生。