【发布时间】:2020-05-23 12:35:11
【问题描述】:
我有一个分配了 20GB 堆内存的应用程序。但是即使堆内存几乎没有使用或不到 50%,我的服务器交换空间也被完全用完了。 Java 是消耗 90% 交换的进程。
只有在重新启动应用程序并显示以下警告后才会释放交换。寻找根本原因以及由此产生的任何影响。如果交换已满,我的应用会无法启动吗?
我在应用程序启动期间在日志中看到的警告:
Java 运行时环境的内存不足,无法继续。 本机内存分配 (mmap) 未能映射 17895718912 字节以提交保留内存。超出交换空间或超出堆资源限制(检查限制或 ulimit)? 生成包含更多信息的错误报告, 它在此位置保存为文件: /XX/myapp/apache-tomcat-7.0.90/bin/hs_err_pid86282.log 2020-01-14T05:17:18.742+0100 [INFO] [oscsPostProcessorRegistrationDelegate$BeanPostProcessorChecker] [org.springframework.aop.aspectj.AspectJAroundAdvice] 类型的 Bean '(inner bean)#1814a032' 不符合被所有人处理的条件BeanPostProcessors(例如:不符合自动代理的条件) ***警告:信息:os::commit_memory(0x00000003fjgh0000, 17895718912, 0) 失败; error='空间不足' (errno=12) Java 运行时环境没有足够的内存来继续。 本机内存分配 (mmap) 未能映射 17895718912 字节以提交保留内存.. Out of 超出交换空间或堆资源限制(检查限制或 ulimit)? 生成包含更多信息的错误报告, 它在此位置保存为文件:
我的 JVM 属性:
/XX/java/bin/java -Djava.util.logging.config.file=/XX/myapp/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -javaagent:/xx/myapp/newrelic/newrelic.jar -Djdk.tls.ephemeralDHKeySize=2048 -Xms20g -Xmx20g -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -Djava.net.preferIPv4Stack=true -Dignore.endorsed.dirs= -classpath /XX/myapp/tomcat/bin/bootstrap.jar:/XX/myapp/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/XX/myapp/tomcat -Dcatalina.home=/XX/myapp/tomcat -Djava.io.tmpdir=/XX/myapp/tomcat/temp org.apache.catalina.startup.Bootstrap start
检查每个进程时的交换使用情况,其 Java 使用 90% 的交换
【问题讨论】:
-
非堆内存,即本机I/O缓冲区……再者,你不能说只使用了50%的堆,当你使用
-Xms20g -Xmx20g和-XX:+AlwaysPreTouch,因为这些选项精确地要求使 20g 堆看起来像是 100% 用于操作系统。 -
你的机器有多少内存?你如何衡量实际的内存/交换消耗?你能发布这样的测量结果吗?您是否尝试使用 jstat、jmap、jcmd 甚至分析器等 JDK 工具监控堆使用情况?
-
谢谢你们。我使用 Newrelic 监控 JVM,可以看到 Heap used [root@vmB0810401 ~]# free -m total used free shared buff/cache available Mem: 28123 22021 562 92 5539 5546 Swap: 2047 272 1775 我不明白为什么在有可用内存时使用 SWAP。而作为 Java 应用程序是另一个问题