【发布时间】:2016-01-11 07:30:39
【问题描述】:
您能帮我解决以下问题吗:
上下文:
我们正在尝试将当前在生产中运行在 Java6(在 Glassfish 上)上的现有应用程序迁移到 Java8(在 Jetty9 上)设置。早些时候,我们能够在 Java7(在 jetty9)上成功迁移相同的设置。但是客户现在决定使用 Java 8。在这个过程中我们遇到了一些内存问题,具体如下:
问题描述:
启动 Jetty 服务器后,java 进程的初始 (RES) 内存使用量约为 5.5g。运行应用程序一段时间后,内存使用量缓慢上升并消耗机器上的最大可用物理内存(8g),最终导致服务器/系统崩溃。
此问题仅在 linux 环境中遇到。 Windows 环境下未发现此类问题。
Profiler 发现:
使用 VisualVM 和 jconsole 监控服务器。在这两个分析器中,JVM 的内存(堆和非堆)使用量都低于分配的限制。
环境详情:
Java Version : 8
Server : Jetty 9.2.10
OS : linux on a virtual machine(Linux version 2.6.32-279.14.1.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) ) #1 SMP Tue Nov 6 23:43:09 UTC 2012
Java Options :
-Xms3072M
-server
-XX:+UnlockDiagnosticVMOptions
-XX:+LogVMOutput
-XX:+UseG1GC
-XX:MaxGCPauseMillis=75
-Xmx3072M
-Xss1024K
-XX:InitialCodeCacheSize=192M
-XX:CodeCacheExpansionSize=3M
-XX:CodeCacheMinimumFreeSpace=3M
-XX:ReservedCodeCacheSize=600M
-XX:MinMetaspaceExpansion=3M
-XX:MaxMetaspaceExpansion=18M
-XX:MaxMetaspaceSize=500M
-XX:MaxDirectMemorySize=288M
-XX:CompressedClassSpaceSize=512M
-XX:ParallelGCThreads=12
-XX:ConcGCThreads=4
-Dsun.rmi.dgc.server.gcInterval=86400000
-Dsun.rmi.dgc.client.gcInterval=86400000
PS:请不要将此标记为重复。我已经阅读了很多关于 stackoverflow 的答案,但没有解决或解决我的问题。
更新
我使用以下 Java 选项启动了 jetty,从那时起内存使用量在 4.5g-4.8g 之间(大约 142 小时)。在我看来它很稳定。我通过 java 选项标志(Xmx 和 MetaspaceSize)保留了大约 2g 的内存,但总是使用额外的 2.5g。这是 Linux 机器上 Java 8 的正常行为吗?
使用的 Java 选项:
-server
-XX:+UnlockDiagnosticVMOptions
-XX:+LogVMOutput
-XX:LogFile=../logs/jvm.log
-XX:+UseG1GC
-XX:MaxGCPauseMillis=75
-XX:ParallelGCThreads=12
-XX:ConcGCThreads=12
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:../logs/gc.log
-XX:NativeMemoryTracking=summary
-Xmx1500m
-Xss256k
-XX:MaxMetaspaceSize=512m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/logs/jetty.hprof
-Dsun.rmi.dgc.server.gcInterval=86400000
-Dsun.rmi.dgc.client.gcInterval=86400000
感谢您的宝贵时间!
【问题讨论】:
-
您是否在某处使用本机代码(明确地说,几乎每个 Java 程序都在后台使用大量本机代码)?就像对 openssl 的本机绑定,还是像 netty.io/wiki/native-transports.html 这样的 http 连接器?那里的内存泄漏不遵守 JVM 限制,因为内存不是由 JVM 管理的。 evanjones.ca/java-native-leak-bug.html 有一些提示如何查找这些问题
-
@zapl 感谢您的意见!我将在我的项目中检查本机绑定。
-
我认为
MaxDirectMemorySize不适用于 mmaped 文件,仅适用于ByteBuffer.allocateDirect(),因此请检查您的堆转储中的DirectByteBuffer实例并计算它们的容量。
标签: java linux memory-management java-8 jvm-arguments