JVM 消耗的本机内存与 java 进程总内存使用量
Native memory consumed by JVM vs java process total memory usage
我有一个很小的 java 控制台应用程序,我想在内存使用方面对其进行优化。它正在 运行,Xmx 设置为仅 64MB。根据不同的监控工具(htop、ps、pmap、Dynatrace),进程的整体内存使用量显示值在 250MB 以上。我 运行 它主要在 Ubuntu 18(也在其他 OS-es 上测试)。
我使用 -XX:NativeMemoryTracking java 参数和本机内存跟踪与 jcmd 来找出为什么在堆外使用了这么多内存。
NMT汇总时显示的值与htop作为Resident Memory显示的值大致相同。
NMT:
Total: reserved=1518873KB, committed=255877KB
htop:
我使用了几个 JVM 参数来减少本机内存消耗(减少堆栈大小、将 GC 更改为串行、Class 数据共享等)。
根据 NMT(malloced 和 mmaped),保留和提交的内存指标总共下降了 ~50MB。
NMT:
Total: reserved=1475110KB, committed=209218KB
我使用的所有工具(htop、ps、pmap、Dynatrace)都没有任何区别。该进程使用的总内存仍然是 250MB。
- 问题是,这是为什么呢?为什么通过 JVM 减少本机内存使用量不会对 java 进程使用的常驻内存产生任何影响?它是否以某种方式预先保留而不发布?
- 是否有任何其他方法可以有效减少整个 java 进程的内存消耗(在已经优化并设置为仅 64MB 的堆之外)?
- 首先,C程序的典型内存表示由以下部分组成。
(https://www.geeksforgeeks.org/memory-layout-of-c-program/)
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堆、JVM栈、JVM本机栈、pc寄存器等。
(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5)
-Xmx
表示JVM最大堆大小,不是Java进程,
(https://java.sun.com/javase/technologies/hotspot/vmoptions.jsp)
并且 JVM 堆只是 Java 堆部分的一部分(在 c 程序内存表示中)。
出于多种原因,NativeMemoryTracking 报告的提交内存可能少于进程的实际驻留集大小 (RSS)。
NMT 只计算某些 JVM 结构。它不计算内存映射文件(包括加载的 .jar 文件),也不计算 libjvm
以外的库分配的内存。即使是标准 class 库(即 libjava
)分配的本机内存也不会显示在 NMT 报告中。
当某些东西使用标准系统分配器 (malloc
) 分配内存然后释放它时,该内存并不总是返回给 OS。系统分配器可能会将已释放的内存保留在池中以备将来重用,但从 OS 的角度来看,该内存被视为已使用(因此包含在 RSS 中)。
and this video 可能会给出其他占用内存的想法,以及如何分析 Java 进程的占用空间。
This post描述了一些减少足迹的想法(合理的和极端的)。
我有一个很小的 java 控制台应用程序,我想在内存使用方面对其进行优化。它正在 运行,Xmx 设置为仅 64MB。根据不同的监控工具(htop、ps、pmap、Dynatrace),进程的整体内存使用量显示值在 250MB 以上。我 运行 它主要在 Ubuntu 18(也在其他 OS-es 上测试)。
我使用 -XX:NativeMemoryTracking java 参数和本机内存跟踪与 jcmd 来找出为什么在堆外使用了这么多内存。
NMT汇总时显示的值与htop作为Resident Memory显示的值大致相同。
NMT:
Total: reserved=1518873KB, committed=255877KB
htop:
我使用了几个 JVM 参数来减少本机内存消耗(减少堆栈大小、将 GC 更改为串行、Class 数据共享等)。 根据 NMT(malloced 和 mmaped),保留和提交的内存指标总共下降了 ~50MB。
NMT:
Total: reserved=1475110KB, committed=209218KB
我使用的所有工具(htop、ps、pmap、Dynatrace)都没有任何区别。该进程使用的总内存仍然是 250MB。
- 问题是,这是为什么呢?为什么通过 JVM 减少本机内存使用量不会对 java 进程使用的常驻内存产生任何影响?它是否以某种方式预先保留而不发布?
- 是否有任何其他方法可以有效减少整个 java 进程的内存消耗(在已经优化并设置为仅 64MB 的堆之外)?
- 首先,C程序的典型内存表示由以下部分组成。 (https://www.geeksforgeeks.org/memory-layout-of-c-program/)
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堆、JVM栈、JVM本机栈、pc寄存器等。
(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5)
-Xmx
表示JVM最大堆大小,不是Java进程, (https://java.sun.com/javase/technologies/hotspot/vmoptions.jsp)
并且 JVM 堆只是 Java 堆部分的一部分(在 c 程序内存表示中)。
出于多种原因,NativeMemoryTracking 报告的提交内存可能少于进程的实际驻留集大小 (RSS)。
NMT 只计算某些 JVM 结构。它不计算内存映射文件(包括加载的 .jar 文件),也不计算
libjvm
以外的库分配的内存。即使是标准 class 库(即libjava
)分配的本机内存也不会显示在 NMT 报告中。当某些东西使用标准系统分配器 (
malloc
) 分配内存然后释放它时,该内存并不总是返回给 OS。系统分配器可能会将已释放的内存保留在池中以备将来重用,但从 OS 的角度来看,该内存被视为已使用(因此包含在 RSS 中)。
This post描述了一些减少足迹的想法(合理的和极端的)。