JVM在堆和缓冲池外泄漏内存



我们有一个java应用程序作为长时间运行的服务(JVM的实际运行时间为31天3小时35分钟)

由于使用了Windows任务管理器,进程使用1075384320 B-将近一GB。

JVM的堆大小限制为256 MB(-Xmx256m)

内存数据

Memory:
Size: 268,435,456 B
Max: 268,435,456 B
Used: 100,000,000 up to 200,000,000 B

-此处无泄漏

缓冲池

Direct:
Count: 137
Memory Used and Total Capacity: 1,348,354 B
Mapped:
Count: 0
Memory Used and Total Capacity: 0 B

-此处无泄漏

我的问题:JVM在哪里使用额外的内存?

其他信息:

Java: version 1.8.0_74 32 bit (Oracle)
Classes:
Total loaded: 17,248
Total unloaded: 35,761
Threads:
Live: 273
Live peak: 285
Daemon: 79
Total started: 486,282

重新启动后,进程大小需要几天的时间才能增长,所以定期重新启动当然会有所帮助,也许使用较新的java版本也可以解决问题,但我想对这种行为有一个解释,例如,在1.8.0 111之前的已知错误,在…-中修复我什么也没找到。

我们在不同的地方使用大约350个这样的装置,所以更换并不容易。

不要忘记在长时间运行的任务中以服务器模式运行JVM!

这种内存泄漏的原因是JVM在客户端模式下运行。我们的解决方案在几家连锁店的旧WindowsXP 32位PC上运行。此平台上JVM的默认模式是客户端模式。

在大多数情况下,我们运行JRE 1.8.0_74-32bit。在我们的应用程序中,这个JVM会泄漏"线程竞技场空间"中的内存——似乎永远不会返回。

通过在JVM启动上设置参数-server切换到服务器模式后,问题消失了。

堆外内存消耗有两个常见原因:

  • 您的应用程序或您正在使用的库之一(例如JDBC驱动程序)以本机方式执行某些操作(通过JNI调用的模块)
  • 您的应用程序或其中一个库以其他方式使用堆外内存,即使用直接缓冲区或"巧妙"使用sun.misc.Unsafe

如本文所述,您可以通过jcmd跟踪本机内存使用情况来验证这一点(您需要重新启动应用程序)。

最新更新