简体   繁体   English

Java 进程占用的 RAM 比堆大小多得多

[英]Java process takes much more RAM than heap size

I have a Java program that has been running for days, it processes incoming messages and forward them out.我有一个已经运行了几天的 Java 程序,它处理传入的消息并将它们转发出去。

A problem I noticed today is that, the heap size I printed via Runtime.totalMemory() shows only ~200M,but the RES column in top command shows it is occupying 1.2g RAM.我今天注意到的一个问题是,我通过 Runtime.totalMemory() 打印的堆大小仅显示 ~200M,但top命令中的 RES 列显示它占用了 1.2g RAM。

The program is not using direct byte buffer.该程序未使用直接字节缓冲区。

How can I find out why JVM is taking this much extra RAM?如何找出 JVM 占用这么多额外 RAM 的原因?

Some other info:其他一些信息:

  • I am using openjdk-1.8.0我正在使用 openjdk-1.8.0
  • I did not set any JVM options to limit the heap size, the startup command is simply: java -jar my.jar我没有设置任何 JVM 选项来限制堆大小,启动命令很简单: java -jar my.jar
  • I tried heap dump using jcmd , the dump file size is only about 15M.我尝试使用jcmd进行堆转储,转储文件大小仅为 15M 左右。
  • I tried pmap , but there seemed to be too much info printed and I don't know which of them is useful.我尝试了pmap ,但似乎打印了太多信息,我不知道其中哪些有用。

You can use VisualVM to monitor what is happening inside your JVM.您可以使用VisualVM监控 JVM 内部发生的情况。 You can also use JConsole for a primary overview.您还可以使用 JConsole 进行主要概述。 It comes with JDK itself.它带有 JDK 本身。 If your JDK is setup with an environment variable, then start it from teriminal with jconsole .如果您的 JDK 是使用环境变量设置的,则使用jconsole从终端启动它。 Then select your application and start monitoring.然后 select 您的应用程序并开始监控。

One thing is that if your heap is not taking much memory, then check from a profiler tool how much has it taken for your non-heap memory.一件事是,如果您的堆没有占用太多 memory,那么从分析器工具中检查您的非堆 memory 占用了多少。 If that amount is high and even after a GC cycle, if its not coming down, then probably you should be looking for a memory leak ( non-heap ).如果该数量很高并且即使在 GC 循环之后,如果它没有下降,那么您可能应该寻找 memory 泄漏(非堆)。

If the non-heap memory is not taking much and everything looks good when you look into the memory using profiling tools, then I guess its the JVM which holds the memory rather releasing them. If the non-heap memory is not taking much and everything looks good when you look into the memory using profiling tools, then I guess its the JVM which holds the memory rather releasing them. So you better check if your GC hasn't work at all or if GC is being forcefully executed using a profiling tool, whether the memory comes down do does it expands or what is happening.因此,您最好检查您的 GC 是否根本没有工作,或者 GC 是否正在使用分析工具强制执行,memory 是否下降,它是否扩展或正在发生什么。 JVM memory and Heap memory are having 2 different behaviors and JVM could assume that it should expand after a GC cycle based on JVM memory and Heap memory are having 2 different behaviors and JVM could assume that it should expand after a GC cycle based on

-XX:MinHeapFreeRatio=
-XX:MaxHeapFreeRatio=

above parameters.以上参数。 So the basic concept behind this is that after a GC cycle, the JVM starts to get measures of free memory and used memory and starts to expand itself or shrink down based on the values for above JVM flags. So the basic concept behind this is that after a GC cycle, the JVM starts to get measures of free memory and used memory and starts to expand itself or shrink down based on the values for above JVM flags. By default they are set to 40 and 70, which you may interested in tuning up.默认情况下,它们设置为 40 和 70,您可能有兴趣进行调整。 This is critical specially in containerized environment.这在容器化环境中尤其重要。

The Java Native Memory Tracking tool is very helpful in situations like this. Java Native Memory 跟踪工具在这种情况下非常有用。 You enable it by starting the JVM with the flag -XX:NativeMemoryTracking=summary .您可以通过使用标志-XX:NativeMemoryTracking=summary启动 JVM 来启用它。

Then when your process is running you can get the stats by executing the following command:然后,当您的进程正在运行时,您可以通过执行以下命令来获取统计信息:

jcmd [pid] VM.native_memory

This will produce a detailed output listing eg the heap size, metaspace size as well as memory allocated directly on the heap.这将生成详细的 output 列表,例如堆大小、元空间大小以及直接在堆上分配的 memory。

You can also use this tool to create a baseline to monitor allocations over time.您还可以使用此工具创建基线以监控一段时间内的分配。

As you will be able to see using this tool, the JVM reserves by default about 1GB for the metaspace, even though just a fraction may be used.正如您使用此工具所看到的,JVM 默认为元空间保留大约 1GB,即使可能只使用一小部分。 But this may account for the RSS usage you are seeing.但这可能是您看到的 RSS 使用情况的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM