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

时间:2017-01-25 15:17:53

标签: java memory-leaks jvm

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

由于Windows任务管理器,该过程使用 1,075,384,320 B - 接近1 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版本也可以解决问题,但我想对此行为有一个解释,即G。 111之前的1.8.0中的已知错误,修复了... - 我没有找到任何东西,但是。

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

2 个答案:

答案 0 :(得分:0)

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

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

您可以使用jcmd as explained here验证此跟踪本机内存使用情况(您需要重新启动应用程序)。

答案 1 :(得分:0)

  

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

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

在大多数情况下,我们运行JRE 1.8.0_74-32bit。在我们的应用程序中,这个JVM在“Thread Arena Space”中泄漏内存 - 似乎没有任何回报。

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