JVM消耗的本地内存与Java进程总内存使用情况
JVM消耗的本地内存与Java进程总内存使用情况
我有一个很小的Java控制台应用程序,我希望它在内存使用方面进行优化。它是在Xmx设置为仅64MB的情况下运行的。根据不同的监控工具(htop,ps,pmap,Dynatrace)显示,这个进程的整体内存使用量超过了250MB。我主要在Ubuntu 18上运行它(也在其他操作系统上测试过)。
我使用了-XX:NativeMemoryTracking java参数和Native Memory Tracking with jcmd,以找出为什么在堆之外使用了更多的内存。
当总结时,NMT显示的值与htop显示的Resident Memory大致相同。
NMT:
Total: reserved=1518873KB, committed=255877KB
htop:
我使用了几个JVM参数来减少本地内存消耗(减少堆栈大小,将GC改为串行,类数据共享等)。
根据NMT显示的结果(malloced和mmaped都减少了),保留和已提交的内存指标总共减少了大约50MB。
NMT:
Total: reserved=1475110KB, committed=209218KB
我正在使用的所有工具(htop、ps、pmap、Dynatrace)都没有任何变化。进程使用的总内存仍然是250MB。
- 问题是为什么?为什么通过JVM减少本机内存使用对Java进程使用的驻留内存没有任何影响?它是否预先保留并未释放?
- 是否有任何其他有效减少整个Java进程的内存消耗的方法(堆之外已经优化并设置为仅64MB)?
admin 更改状态以发布 2023年5月22日
- 首先,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本地栈,程序计数器等。
(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)少的承诺内存。\n
- \n
- NMT 仅统计特定的 JVM 结构。它不会计算内存映射文件(包括已加载的 .jar 文件)或由除 libjvm 之外的库分配的内存。甚至标准类库(即 libjava)分配的本机内存也不在 NMT 报告中显示。\n
- 当某个东西使用标准系统分配器(malloc)分配内存,然后释放它时,这个内存并不总是返回给操作系统。系统分配器可能会将已释放的内存保留在一个池中以供将来重用,但从操作系统的角度来看,这个内存被视为已使用(因此包含在 RSS 中)。\n
\n
\n
\n这篇答案和这个视频可能会让您了解什么占用了内存,以及如何分析 Java 进程的占用空间。\n这篇文章描述了一些想法(合理和极端),以减小占用空间。