【问题标题】:Native memory consumed by JVM vs java process total memory usageJVM 消耗的本机内存与 Java 进程的总内存使用量
【发布时间】:2020-10-19 10:23:45
【问题描述】:

我有一个小型 Java 控制台应用程序,我想在内存使用方面进行优化。它在 Xmx 设置为仅 64MB 的情况下运行。根据不同的监控工具(htop、ps、pmap、Dynatrace),进程的整体内存使用情况显示值在 250MB 以上。我主要在 Ubuntu 18 上运行它(也在其他操作系统上测试过)。

我使用了 -XX:NativeMemoryTracking java param 和 Native Memory Tracking with jcmd 来找出为什么在堆外使用了这么多内存。

NMT 在汇总时显示的值或多或少与 htop 作为 Resident Memory 显示的值相同。

神经机器翻译

Total: reserved=1518873KB, committed=255877KB

htop

我使用了几个 JVM 参数来减少本机内存消耗(减少堆栈大小、将 GC 更改为串行、类数据共享等)。 根据 NMT(malloced 和 mmaped),保留和提交的内存指标都下降了约 50MB。

神经机器翻译

Total: reserved=1475110KB, committed=209218KB

我使用的所有工具(htop、ps、pmap、Dynatrace)完全没有区别。该进程使用的总内存仍为 250MB。

  1. 问题是,为什么会这样?为什么减少 JVM 的本机内存使用量不会对 java 进程使用的常驻内存产生任何影响?它是否以某种方式预先保留而不发布?
  2. 有没有其他方法可以有效减少整个 java 进程的内存消耗(在已经优化并设置为仅 64MB 的堆之外)?

【问题讨论】:

  • 看起来这对你有用stackoverflow.com/questions/6785754/…
  • 谢谢@codinnvrends,但我还是不明白。我知道 JVM 在堆旁边使用内存。我可以通过 NMT 看到完整的细节,并且我正在寻求优化。我仍然不明白为什么即使 NMT 显示更少的内存消耗在操作系统级别上也没有区别

标签: java memory operating-system jvm


【解决方案1】:

由于多种原因,NativeMemoryTracking 报告的提交内存可能少于进程的实际驻留集大小 (RSS)。

  • NMT 只计算某些 JVM 结构。它不计算内存映射文件(包括加载的 .jar 文件),也不计算 libjvm 以外的库分配的内存。甚至由标准类库(即libjava)分配的本机内存也不会显示在 NMT 报告中。

  • 当使用标准系统分配器 (malloc) 分配内存然后释放它时,这些内存并不总是返回给操作系统。系统分配器可能会将释放的内存保留在池中以供将来重用,但从操作系统的角度来看,此内存被认为已使用(因此包含在 RSS 中)。

This answerthis video 可能会告诉您还有什么需要内存,以及如何分析 Java 进程的足迹。

This post 描述了一些关于减少占用空间的想法(合理的和极端的)。

【讨论】:

  • 感谢@apangin 提供详细的答案和链接。我之前已经阅读过 Aleksey Shipilёv 的帖子 - 太棒了。我了解 NMT 显示的已提交内存报告少于进程的实际 RSS。我仍然希望看到至少一些改进。我认为一定是这样的情况,即使 NMT 显示比没有 JVM 调整时少 50MB,已经分配了更多内存并且现在没有返回给操作系统
  • @KnotGillCup 另一个可能的原因是,并非 NMT 显示的所有“已提交”内存实际上都会增加进程占用空间。例如。当您减小 Java 堆栈大小时,NMT 会报告相应的已提交内存减少,但这不会影响 RSS。详情请见JDK-8191369
  • 确实如此。我所做的其中一件事是减少堆栈大小。顺便说一句,很棒的视频。真的很喜欢。
【解决方案2】:
  A typical memory representation of C program consists of following sections.

  1. Text segment
  2. Initialized data segment
  3. Uninitialized data segment
  4. Stack
  5. Heap
  • JVM内存包括:JVM heap、JVM Stack、JVM native stack、The pc Register等。

(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5)

而 JVM 堆只是 Java 堆部分的一部分(以 c 程序内存表示)。

【讨论】:

  • 谢谢,@SvenAugustus 但这并不能回答我的任何问题。我减少了 JVM 堆栈大小、GC 分配的内存等等,但整个进程内存与使用默认 JVM 选项运行进程时的内存相同..
猜你喜欢
  • 2022-06-14
  • 2021-03-29
  • 1970-01-01
  • 2020-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
相关资源
最近更新 更多