老一代内存使用量的增长总是意味着 Java 中的内存泄漏?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23253605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:32:06  来源:igfitidea点击:

Growth in old gen memory usage always means memory leak in java?

javamemory-leaks

提问by zhengyu

We have several VMs which are running data service in production, client sends Restful HTTP requests to data service, the load is kind of heavy (500 requests per second per host in general) and load is always balanced on each VM. We have same configuration on all hosts (2 CPUs, -Xms2048m -Xmx4096m -XX:MaxPermSize=192m -XX:NewSize=512m -XX:MaxNewSize=512M -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError)

我们有几个虚拟机在生产中运行数据服务,客户端向数据服务发送 Restful HTTP 请求,负载有点重(通常每个主机每秒 500 个请求)并且每个虚拟机上的负载总是平衡的。我们在所有主机上都有相同的配置(2 个 CPU,-Xms2048m -Xmx4096m -XX:MaxPermSize=192m -XX:NewSize=512m -XX:MaxNewSize=512M -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError

Two days ago, we saw old gen heap usage start growing on 5 of those VMs (300 MB per day), old gen heap usage on other ones stay the same (around 80 MB), we are trying to identify the root cause, may I ask if this is a memory leak issue or just a normal situation? Does growth in old gen memory usage always mean memory leak in java?

两天前,我们看到其中 5 个虚拟机上的旧代堆使用量开始增长(每天 300 MB),其他虚拟机上的旧代堆使用量保持不变(大约 80 MB),我们正在尝试找出根本原因,可能请问这是内存泄漏问题还是正常情况?老一代内存使用量的增长是否总是意味着 Java 中的内存泄漏?

Thanks.

谢谢。

Update: We just restarted those 5 hosts yesterday, old gen heap usage on all of them went back to normal as other ones, however, after the peak load we had this morning, the old gen heap usage on one of them started growing again...

更新:我们昨天刚刚重新启动了这 5 台主机,所有主机上的旧代堆使用率都像其他主机一样恢复正常,但是,在我们今天早上的峰值负载之后,其中一台主机上的旧代堆使用率又开始增长。 ..

采纳答案by spudone

Does growth in old gen memory usage always mean memory leak in java?

老一代内存使用量的增长是否总是意味着 Java 中的内存泄漏?

Not necessarily.

不必要。

The concurrent mark sweep garbage collector does not compact the old gen during collection. So under sufficient memory load, it's possible to get a large amount of fragmentation, making it impossible to reclaim enough memory to allow promotion of tenured objects into the old gen space.

并发标记清除垃圾收集器在收集过程中不会压缩旧代。因此,在足够的内存负载下,可能会出现大量碎片,从而无法回收足够的内存以将老旧对象提升到旧代空间。

Try turning on these params and see what's going on:

尝试打开这些参数,看看发生了什么:

-XX:+PrintGCDetails -XX:+PrintPromotionFailure -XX:PrintFLSStatistics=1

-XX:+PrintGCDetails -XX:+PrintPromotionFailure -XX:PrintFLSStatistics=1

Look for promotion failures and frequent full GC sweeps that fail to free up a lot of memory.

查找无法释放大量内存的升级失败和频繁的 full GC 扫描。

If you're using Java 7 or higher you can try switching to the G1 collector(-XX:+UseG1GC instead of -XX:+UseConcMarkSweepGC). This is a compacting collector which avoids some of the above issues.

如果您使用的是 Java 7 或更高版本,您可以尝试切换到G1 收集器(-XX:+UseG1GC 而不是 -XX:+UseConcMarkSweepGC)。这是一个压缩收集器,它避免了上述一些问题。

If you're still running into problems after that, then I'd look to your code to see if something is hanging onto object references when it shouldn't.

如果在那之后您仍然遇到问题,那么我会查看您的代码,看看是否有某些东西挂在不应该挂在对象引用上。

Edit: since this is happening on some hosts and not others, I'd lean towards a code issue, perhaps related to unexpected user input, since it only occurs sporadically.

编辑:由于这发生在某些主机而不是其他主机上,我倾向于代码问题,可能与意外的用户输入有关,因为它只是偶尔发生。

回答by Natan Cox

It sounds like what you are describing is a memory leak. Because for me a memory leak is when your memory increases in time without any good reason or without developers understanding why. Which probably implies that some data you actually do not need is still kept in memory probably as a result of a bug.

听起来您所描述的是内存泄漏。因为对我来说,内存泄漏是指您的内存在没有任何充分理由或开发人员不了解原因的情况下随时间增加。这可能意味着您实际上不需要的某些数据可能由于错误而仍保留在内存中。

I would consider using a good profiler to get to the root cause. It is probably easiest. I don't know if I'm allowed to name products here but JProfiler saved my team in multiple projects I worked on.

我会考虑使用一个好的分析器来找到根本原因。这可能是最简单的。我不知道我是否可以在这里命名产品,但 JProfiler 将我的团队保存在我参与的多个项目中。