xmx java_为什么我的Java进程比Xmx消耗更多的内存?

xmx java

你们有些人去过那里。 您已经在启动脚本中添加了-Xmx选项,并放松了下来,因为您知道Java进程将不会消耗比经过微调的选项所允许的更多的内存。 然后,您感到非常讨厌。 要么自己检查开发/测试框中的过程表,要么事情真的变坏了,然后由操作人员在半夜打电话给您,告诉您您要生产的4G内存已用完。 而且该应用程序刚刚终止。 RAM内存
那么幕后到底发生了什么呢? 为什么进程消耗的内存比分配的更多? 是bug还是完全正常的东西? 忍受我,我将指导您进行到底。

首先,它的一部分肯定可以是内存泄漏的恶意本机代码。 但是在99%的情况下,这完全是JVM的正常行为。 通过-Xmx开关指定的内容是限制应用程序堆消耗的内存。

除了堆以外,您的应用程序还使用内存中的其他区域,即permgen和堆栈大小。 因此,为了限制这些值,还应该分别指定-XX:MaxPermSize-Xss选项。 简而言之,您可以使用以下公式预测应用程序的内存使用情况

Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]

但是,除了您的应用程序占用的内存外,JVM本身还需要一些空间 。 对它的需求来自几个不同的原因:

  • 垃圾收集。 您可能还记得,Java是一种垃圾收集语言。 为了使垃圾收集器知道哪些对象适合进行收集,它需要跟踪对象图。 因此,这是内部簿记丢失的部分内存。 特别是G1以其对额外内存的过度需求而闻名,因此请注意这一点。
  • JIT优化。 Java虚拟机在运行时优化代码。 同样,要知道要优化的部分,需要跟踪某些代码部分的执行情况。 同样,您将失去记忆。
  • 堆外分配。 如果您碰巧使用了堆外内存,例如,在自己使用直接或映射的ByteBuffer或通过一些聪明的第三方API时,那就瞧瞧-您正在将堆扩展到实际上无法通过JVM配置控制的范围。
  • JNI代码。 例如,当您以2类数据库驱动程序的格式使用本机代码时,您将再次在本机内存中加载代码。
  • 元空间。 如果您是Java 8的较早采用者,那么您将使用元空间而不是旧的permgen来存储类声明。 这是无限的,并且在JVM的本机部分中。

除了上面列出的原因之外,您最终可能还会由于其他原因而使用内存,但是我希望我能说服您JVM内部消耗了大量内存。 但是,有没有一种方法可以预测实际需要多少内存呢? 或者至少了解它消失的位置以便进行优化?

正如我们从痛苦的经历中发现的那样-无法以合理的精度进行预测。 JVM开销的范围从几个百分点到几百个百分点。 您最好的朋友还是古老的尝试和错误。 因此,您需要以类似于生产环境和度量的负载运行应用程序。

衡量额外的开销是微不足道的–只需使用OS内置工具(在Linux上排名靠前 ,在OS X上使用Activity Monitor ,在Windows上使用Task Manager )监视进程即可找出实际的内存消耗。 从实际消耗中减去堆大小和permgen大小,您将看到开销。

现在,如果需要减少开销,您想了解它实际消失的位置。 在这种情况下,我们发现Mac OS X上的vmmapLinux上的pmap是真正有用的工具。 我们自己没有使用vmmap端口连接Windows,但似乎也有Windows迷的工具。

以下示例说明了这种情况。 我使用以下启动参数启动了Jetty:

-Xmx168m -Xms168m -XX:PermSize=32m -XX:MaxPermSize=32m -Xss1m

知道我的应用程序中启动了30个线程后,我可能会希望无论如何我的内存使用量都不会超过230M。 但是现在当我在Mac OS X上查看“ 活动监视器”时,会看到一些不同的东西。

实际内存使用量已超过320M。 现在,在vmmap <pid>输出的帮助下, 深入了解该过程,我们开始了解内存在哪里消失。 让我们看一些示例:

下面说我们丢失了将近2MB丢失到内存映射的rt.jar库。

mapped file            00000001178b9000-0000000117a88000 [ 1852K] r--/r-x SM=ALI  /Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/rt.jar

下一节说明,对于加载的特定动态库,我们正在使用〜6MB

__TEXT                 0000000104573000-0000000104c00000 [ 6708K] r-x/rwx SM=COW  /Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/server/libjvm.dylib

在这里,我们没有线程25-30,每个线程为其堆栈和堆栈防护分配1MB

Stack 000000011a5f1000-000000011a6f0000 [ 1020K] rw-/rwx SM=ZER thread 25 Stack 000000011aa8c000-000000011ab8b000 [ 1020K] rw-/rwx SM=ZER thread 27 Stack 000000011ab8f000-000000011ac8e000 [ 1020K] rw-/rwx SM=ZER thread 28 Stack 000000011ac92000-000000011ad91000 [ 1020K] rw-/rwx SM=ZER thread 29 Stack 000000011af0f000-000000011b00e000 [ 1020K] rw-/rwx SM=ZER thread 30
STACK GUARD 000000011a5ed000-000000011a5ee000 [ 4K] ---/rwx SM=NUL stack guard for thread 25 STACK GUARD 000000011aa88000-000000011aa89000 [ 4K] ---/rwx SM=NUL stack guard for thread 27 STACK GUARD 000000011ab8b000-000000011ab8c000 [ 4K] ---/rwx SM=NUL stack guard for thread 28 STACK GUARD 000000011ac8e000-000000011ac8f000 [ 4K] ---/rwx SM=NUL stack guard for thread 29 STACK GUARD 000000011af0b000-000000011af0c000 [ 4K] ---/rwx SM=NUL stack guard for thread 30

我希望我能对预测和测量实际内存消耗这一棘手的任务有所了解。


翻译自: https://www.javacodegeeks.com/2013/06/why-does-my-java-process-consume-more-memory-than-xmx.html

xmx java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值