【问题标题】:Java process consuming 90% of swap spaceJava 进程消耗 90% 的交换空间
【发布时间】: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 应用程序是另一个问题

标签: jvm tomcat7 swap


【解决方案1】:

您的 Java 进程并非仅来自堆内存,请注意this for a good example

现在,您说您拥有28GB 的 RAM,您将其中的20GB 分配给堆。您不仅要保留虚拟内存,还可以通过AlwaysPreTouch提交它(我现在怀疑你是否理解它的作用)。因此,您的操作系统将 RAM 的20GB 映射到您的进程(简化解释)。

即使您看到只有 50% 被占用,您使用的垃圾收集器 - 不会 将内存释放回操作系统,因此整个 20GC 始终 /em> 被占用,不能被其他进程重用。因此,测量或监控堆是没有意义的。

您的进程因Native memory allocation (mmap) failed to map... 而失败,如上所述,这与堆无关。它在本机内存中失败,这是!= 堆。我也不知道您的应用程序的细节,但-XX:+DisableExplicitGC 可能不是一个好的选择;相反,您可以通过-XX:+ExplicitGCInvokesConcurrent 启用并发调用(如果您的 GC 支持)。

您似乎也在使用CMS 垃圾收集器-已弃用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 2019-06-19
    • 2012-08-31
    • 2014-06-17
    • 2019-09-14
    • 1970-01-01
    相关资源
    最近更新 更多