Java虚拟机消耗的本地内存 vs Java进程的总内存使用量

huangapple go评论73阅读模式
英文:

Native memory consumed by JVM vs java process total memory usage

问题

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

我使用了-XX:NativeMemoryTracking Java参数和使用jcmd进行本地内存跟踪,以找出为什么在堆外使用了更多的内存。

NMT显示的值在总结时与htop显示的驻留内存值基本相同。

NMT

总计:reserved=1518873KB,committed=255877KB

htop

Java虚拟机消耗的本地内存 vs Java进程的总内存使用量

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

NMT

总计:reserved=1475110KB,committed=209218KB

我使用的所有工具(htop、ps、pmap、Dynatrace)都没有显示任何差异。进程使用的总内存仍然是250MB。

  1. 问题是,为什么通过JVM减少本地内存使用对Java进程使用的驻留内存没有任何影响?它是否在前面以某种方式预留,并且没有释放?
  2. 是否有其他方法可以有效减少整个Java进程的内存消耗(堆外内存已经优化并设置为仅64MB)?
英文:

I have a tiny java console application which I would like to optimize in terms of memory usage. It is being run with Xmx set to only 64MB. The overall memory usage of the process according to different monitoring tools (htop, ps, pmap, Dynatrace) shows values above 250MB. I run it mostly on Ubuntu 18 (tested on other OS-es as well).

I've used -XX:NativeMemoryTracking java param and Native Memory Tracking with jcmd to find out why so much more memory is used outside of the heap.

The values displayed by NMT when summarized were more or less the same as the ones shown by htop as Resident Memory.

NMT:

Total: reserved=1518873KB, committed=255877KB

htop:

Java虚拟机消耗的本地内存 vs Java进程的总内存使用量

I've used several JVM parameters to reduce native memory consumption (reduced stack size, changed GC to serial, Class Data Sharing etc).
Both reserved and committed memory metrics went down according to NMT (both malloced and mmaped) by let's say ~50MB in total.

NMT:

Total: reserved=1475110KB, committed=209218KB

All the tools that I'm using (htop, ps, pmap, Dynatrace) show no difference at all. Total memory used by the process is still 250MB.

  1. The question is, why is that? Why reducing native memory usage by JVM does not make any effect on the resident memory used by the java process? Is it reserved somehow upfront and not released?
  2. Is there any other way to effectively reduce memory consumption by the whole java process (outside of the heap which is already optimized and set to only 64MB)?

答案1

得分: 7

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

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

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

这个答案这个视频可能会让你了解还有哪些因素会占用内存,以及如何分析Java进程的占用空间。

这篇文章介绍了一些关于减少内存占用的想法(既有合理的,也有极端的)。

英文:

NativeMemoryTracking may report less committed memory than the actual Resident Set Size (RSS) of a process for multiple reasons.

  • NMT counts only certain JVM structures. It does not count memory mapped files (including loaded .jar files), nor memory allocated by libraries other than libjvm. Even native memory allocated by the standard class library (i.e. libjava) is not shown in NMT report.

  • When something allocates memory with a standard system allocator (malloc) and then releases it, this memory isn't always returned back to the OS. The system allocator may keep released memory in a pool for future reuse, but from the OS perspective this memory is considered used (and thus included in RSS).

This answer and this video may give an idea what else takes memory, and how to analyze footprint of a Java process.

This post describes some ideas (both reasonable and extreme) on reducing footprint.

答案2

得分: 1

Sure, here are the translations of the provided content:


  C程序的典型内存表示包括以下几个部分。

  1. 代码段(Text segment)
  2. 初始化数据段(Initialized data segment)
  3. 未初始化数据段(Uninitialized data segment)
  4. 栈(Stack)
  5. 堆(Heap)
  • JVM内存包括:JVM堆(JVM heap)、JVM栈(JVM Stack)、JVM本地栈(JVM native stack)、程序计数器(pc Register)等。

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

而且JVM堆只是Java堆部分的一部分(在C程序内存表示中)。


英文:
  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 memory includes: JVM heap, JVM Stack, JVM native stack, The pc Register , and so on.

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

and the JVM heap just a part of Java Heap section (in c program memory representation).

huangapple
  • 本文由 发表于 2020年6月29日 17:22:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/62635023.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定