简体   繁体   English

JVM内存使用失控

[英]JVM memory usage out of control

I have a Tomcat webapp which does some pretty memory and CPU-intensive tasks on the behalf of clients. 我有一个Tomcat webapp,它代表客户端执行一些漂亮的内存和CPU密集型任务。 This is normal and is the desired functionality. 这是正常的,是所需的功能。 However, when I run Tomcat, memory usage skyrockets over time to upwards of 4.0GB at which time I usually kill the process as it's messing with everything else running on my development machine: 但是,当我运行Tomcat时,内存使用量会随着时间的推移而猛增至4.0GB以上,此时我通常会杀死该进程,因为它会破坏我在开发计算机上运行的所有其他内容:

在此输入图像描述

I thought I had inadvertently introduced a memory leak with my code, but after checking into it with VisualVM, I'm seeing a different story: 我以为我无意中用我的代码引入了内存泄漏,但在用VisualVM检查后,我看到了一个不同的故事:

在此输入图像描述

VisualVM is showing the heap as taking up approximately a GB of RAM, which is what I set it to do with CATALINA_OPTS="-Xms256m -Xmx1024" . VisualVM显示堆占用大约一GB的RAM,这就是我用CATALINA_OPTS="-Xms256m -Xmx1024"

Why is my system seeing this process as taking up a ton of memory when according to VisualVM, it's taking up hardly any at all? 根据VisualVM的说法,为什么我的系统认为这个过程占用了大量的内存,它几乎没有占用任何内容?


After a bit of further sniffing around, I'm noticing that if multiple jobs are running simultaneously in the applications, memory does not get freed. 经过一番进一步的嗅探,我注意到如果在应用程序中同时运行多个作业,则内存不会被释放。 However, if I wait for each job to complete before submitting another to my BlockingQueue serviced by an ExecutorService , then memory is recycled effectively. 但是,如果我在将另一个作业提交给由ExecutorService提供服务的BlockingQueue之前等待每个作业完成,那么内存将被有效地回收。 How can I debug this? 我该怎么调试呢? Why would garbage collection/memory reuse differ? 为什么垃圾收集/内存重用会有所不同?

You can't control what you want to control , -Xmx only controls the Java Heap, it doesn't control consumption of native memory by the JVM, which is consumed completely differently based on implementation. 您无法控制要控制的内容-Xmx仅控制Java堆,它不控制JVM对本机内存的消耗,而JVM根据实现完全不同地使用。 VisualVM is only showing you what the Heap is comsuming, it doesn't show what the entire JVM is consuming as native memory as an OS process. VisualVM只显示Heap正在消耗的内容,它不会显示整个JVM作为本机内存消耗的操作系统进程。 You will have to use OS level tools to see that, and they will report radically different numbers, usually much much larger than anything VisualVM reports, because the JVM uses up native memory in an entirely different way. 您将不得不使用操作系统级工具来查看它,并且它们将报告完全不同的数字,通常比VisualVM报告的任何数字都大得多,因为JVM以完全不同的方式使用本机内存

From the following article Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux ) 从以下文章感谢内存(了解JVM如何在Windows和Linux上使用本机内存)

Maintaining the heap and garbage collector use native memory you can't control. 维护堆和垃圾收集器使用您无法控制的本机内存。

More native memory is required to maintain the state of the memory-management system maintaining the Java heap. 需要更多的本机内存来维护维护Java堆的内存管理系统的状态。 Data structures must be allocated to track free storage and record progress when collecting garbage. 必须分配数据结构以跟踪免费存储并记录收集垃圾时的进度。 The exact size and nature of these data structures varies with implementation, but many are proportional to the size of the heap. 这些数据结构的确切大小和性质随实现而变化,但许多与堆的大小成比例。

and the JIT compiler uses native memory just like javac would 并且JIT编译器使用本机内存,就像javac一样

Bytecode compilation uses native memory (in the same way that a static compiler such as gcc requires memory to run), but both the input (the bytecode) and the output (the executable code) from the JIT must also be stored in native memory. 字节码编译使用本机内存(与gcc等静态编译器需要运行内存的方式相同),但JIT的输入(字节码)和输出(可执行代码)也必须存储在本机内存中。 Java applications that contain many JIT-compiled methods use more native memory than smaller applications. 包含许多JIT编译方法的Java应用程序比较小的应用程序使用更多的本机内存。

and then you have the classloader(s) which use native memory 然后你有使用本机内存的类加载器

Java applications are composed of classes that define object structure and method logic. Java应用程序由定义对象结构和方法逻辑的类组成。 They also use classes from the Java runtime class libraries (such as java.lang.String) and may use third-party libraries. 它们还使用Java运行时类库(例如java.lang.String)中的类,并且可以使用第三方库。 These classes need to be stored in memory for as long as they are being used. 只要它们被使用,这些类就需要存储在内存中。 How classes are stored varies by implementation. 如何存储类因实现而异。

I won't even start quoting the section on Threads, I think you get the idea that -Xmx doesn't control what you think it controls, it controls the JVM heap, not everything goes in the JVM heap, and the heap takes up way more native memory that what you specify for management and book keeping. 我甚至不会开始引用关于Threads的部分,我想你会认为-Xmx不能控制你认为它控制的是什么,它控制着JVM堆,而不是JVM堆中的所有内容,并且堆占用了更多的本机记忆,你指定的管理和簿记。

Plain and simple the JVM uses more memory than what is supplied in -Xms and -Xmx and the other command line parameters. 简单而简单的JVM使用的内存比-Xms-Xmx以及其他命令行参数中提供的内存更多。

Here is a very detailed article on how the JVM allocates and manages memory , it isn't as simple as what you are expected based on your assumptions in your question, it is well worth a comprehensive read. 这里有一篇关于JVM如何分配和管理内存非常详细的文章 ,它并不像你在问题中的假设所期望的那样简单,值得全面阅读。

ThreadStack size in many implementations have minimum limits that vary by Operating System and sometimes JVM version; 许多实现中的ThreadStack大小具有最小限制,这些限制因操作系统和JVM版本而异; the threadstack setting is ignored if you set the limit below the native OS limit for the JVM or the OS ( ulimit on *nix has to be set instead sometimes ). 如果将限制设置为低于JVM或OS的本机操作系统限制,则会忽略threadstack设置(有时必须设置ulix on * nix)。 Other command line options work the same way, silently defaulting to higher values when too small values are supplied. 其他命令行选项以相同的方式工作,当提供的值太小时,默认默认为更高的值。 Don't assume that all the values passed in represent what are actually used. 不要假设传入的所有值都代表实际使用的值。

The Classloaders, and Tomcat has more than one, eat up lots of memory that isn't documented easily. 类加载器和Tomcat有不止一个,占用了大量内存,而这些内存很难被记录下来。 The JIT eats up a lot of memory, trading space for time, which is a good trade off most of the time. JIT占用了大量的内存,随着时间的推移交易空间,这在大多数情况下是一个很好的交易。

You should also check for CPU usage and garbage collector. 您还应该检查CPU使用情况和垃圾收集器。
It is possible that garbage collection pauses and the CPU gc consumes further slow down your machine. 垃圾收集可能会暂停 ,并且CPU gc会进一步降低机器的运行速度。

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

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