【问题标题】:Java Memory exceeding 512mb despite having set -Xmx300m -Xss512k -XX:MetaspaceSize=100M?尽管设置了 -Xmx300m -Xss512k -XX:MetaspaceSize=100M,Java 内存仍超过 512mb?
【发布时间】:2018-05-27 05:50:47
【问题描述】:

我已使用以下 vm 选项将 java 应用程序部署到 Heroku:

-Xmx300m -Xss512k -XX:MetaspaceSize=100M

尽管如此,我的应用程序始终从 Heroku 收到 Error R14 (Memory Quota Exceeded) 错误。这是因为内存占用达到540+mb(配额为512mb)。

当我在 VM args 中只为它分配 400mb 时,java 应用程序如何占用超过 500mb?我是否缺少 VM arg?

我预计 JVM 在达到 512mb 内存之前会 OOM(但它只会增加超出我设置的限制)。

也许我完全误解了这些 VM 参数的工作原理?

对此的任何帮助将不胜感激。

注意事项:

  • 我正在使用 java 8
  • 我的procfile如下:

    web: java -Xmx300m -Xss512k -XX:MetaspaceSize=100M -javaagent:./lib/heroku-javaagent-2.0.jar=stdout=true,lxmem=true -Dserver.port=$PORT -Dspring.profiles.active=heroku -cp ./app.jar          org.springframework.boot.loader.JarLauncher
    

上面的java代理在日志中吐出如下细节:

Dec 13 11:45:54 app/web.1:  measure.mem.jvm.heap.used=177M measure.mem.jvm.heap.committed=212M measure.mem.jvm.heap.max=273M 
Dec 13 11:45:54 app/web.1:  measure.mem.jvm.nonheap.used=129M measure.mem.jvm.nonheap.committed=132M measure.mem.jvm.nonheap.max=0M 
Dec 13 11:45:54 app/web.1:  measure.mem.jvm.direct.used=0M measure.mem.jvm.direct.count=0 measure.mem.jvm.direct.capacity=74M 
Dec 13 11:45:54 app/web.1:  measure.mem.jvm.mapped.used=0M measure.mem.jvm.mapped.count=0 measure.mem.jvm.mapped.capacity=0M 
Dec 13 11:45:54 app/web.1:  measure.mem.linux.vsz=5817M measure.mem.linux.rss=543M 

【问题讨论】:

  • 您的应用程序本身可能存在内存泄漏,您可以在本地部署您的应用程序,并在 visualVM 或 Jconsole 中查看内存分配行为。
  • 嗨@kakurala。如果发生内存泄漏,JVM OOM 会不会超过它的极限?
  • 这里的关键是measure.mem.jvm.nonheap.used=129M,这意味着有129MB的堆外内存正在使用,不关心堆限制。堆外内存可以被直接ByteBuffers、内存映射文件等使用。 heroku 是否认为配额包括 JVM 除了应用程序之外正在使用的内存,还是仅包括应用程序?
  • 除了 Java Heap 和 Metaspace 之外,还有很多东西可以使用内存:代码缓存、Direct ByteBuffers、线程堆栈、本机库...
  • 代码缓存和元空间是完全不同的区域。 -Xss 是每个线程的限制,即更多线程 => 更多内存。使用Native Memory Tracking 获取有关 JVM 内存使用情况的详细报告(但仍不包括内存映射文件和本机库)。

标签: java heroku jvm


【解决方案1】:

当我在 VM args 中只为它分配 400mb 时,java 应用程序如何占用超过 500mb?我是否缺少 VM arg?

JVM 有许多类别的内存,包括堆、元空间、线程堆栈、代码缓存等等。甚至可以通过 JNI 分配 JVM 无法解释的内存。看看this blog post on JVM memory

我预计 JVM 在达到 512mb 内存之前会 OOM(但它只会增加超出我设置的限制)。

大多数 OOM 错误仅在堆空间用完时发生。在您的情况下,您有足够的堆空间,但所有其他类别都在加起来并使您超过 512mb 的限制。

您可以尝试将Xmx 降低到-Xmx256m。低于此值,您可能会开始收到 OOM 错误。

您可能还想检查您的代码是否存在 IO 缓冲区泄漏。如果没有正确关闭,它们有时会导致本机内存(堆外)泄漏。最后,检查您的任何依赖项(第三方库)是否正在使用 JNI 或分配本机内存。

【讨论】:

    【解决方案2】:
    -Xmx256m -XX:+UseContainerSupport
    

    为我做的。使用 Heroku 默认值(即 -Xmx300m)超过了 Dyno 的 512MB 阈值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-13
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      • 2017-09-25
      • 1970-01-01
      相关资源
      最近更新 更多