我有一个Tomcat webapp,它代表客户端执行一些相当大的内存和CPU密集型任务。这是正常的,也是所需的功能。但是,当我运行Tomcat时,内存使用量会随着时间的推移而猛增,达到4.0GB以上,这时我通常会关闭该进程,因为它会扰乱我开发机器上运行的其他所有内容:
我以为我的代码无意中引入了内存泄漏,但在使用VisualVM检查它之后,我看到了一个不同的情况:
VisualVM显示该堆占用大约一GB的RAM,这是我用catalina_opts=“-xms256m-xmx1024”
设置它的目的。
经过一些进一步的搜索,我注意到如果多个作业同时在应用程序中运行,内存不会被释放。但是,如果在将另一个作业提交到由executorservice
提供服务的blockingqueue
之前,等待每个作业完成,那么内存将有效地回收。我如何调试这个?为什么垃圾收集/内存重用会有所不同?
您不能控制您想要控制的内容,-xmx
只控制Java堆,它不控制JVM对本机内存的消耗,而JVM对本机内存的消耗根据实现完全不同。VisualVM只向您显示了堆所消耗的资源,它并不显示整个JVM作为一个OS进程所消耗的本机内存。您必须使用OS级别的工具来了解这一点,它们将报告完全不同的数字,通常比VisualVM报告的数字要大得多,因为JVM以完全不同的方式使用本机内存。
下面的文章感谢内存(了解JVM如何在Windows和Linux上使用本机内存)
维护堆和垃圾回收器使用的是您无法控制的本机内存。
然后就有了使用本机内存的类加载器
Java应用程序由定义对象结构和方法逻辑的类组成。它们还使用Java运行时类库(如Java.lang.String)中的类,并可能使用第三方库。只要这些类正在使用,它们就需要存储在内存中。类的存储方式因实现而异。
我甚至不会开始引用线程部分,我想您会理解-xmx
并不控制您认为它控制的东西,它控制的是JVM堆,不是所有的东西都在JVM堆中,而且堆占用的本机内存比您指定的用于管理和记账的内存多得多。
这里有一篇关于JVM如何分配和管理内存的非常详细的文章,它并不像您在问题中的假设所期望的那样简单,它非常值得一读。
许多实现中的线程栈大小都有最小限制,这些限制因操作系统而异,有时也因JVM版本而异;如果将限制设置为JVM或OS的本机OS限制以下,则忽略threadstack设置(有时必须设置*nix上的ulimit)。其他命令行选项的工作方式相同,当提供的值太小时,默认为较高的值。不要假设所有传入的值都代表实际使用的东西。
类加载器和Tomcat有多个类加载器,会消耗大量不容易记录的内存。JIT消耗了大量内存,以空间换取时间,这在大多数情况下是一种很好的折衷。
问题内容: jvm进程的内存使用量一直在增加,并且从未减少。我通过在linux服务器上执行top进行检查。该应用程序正在将作业调度到群集(使用Quartz + SunJava DRMAA API) Java堆空间在应用程序生命周期内保持在限制之内,但是jvm进程显示内存使用率稳定增长且从未下降。 这是内存泄漏吗?如果是这样,为什么堆空间在限制之内。有人可以解释一下。 更新: 当我通过jconsol
我的问题是,如果我从java代码调用Shell脚本,脚本使用的内存,是从JVM堆空间分配,还是使用系统内存空间。
我们Java开发人员有时会使用来确保我们为每个特定于线程的堆栈提供了1MB的空间。现在,我经常感到困惑,JVM从哪里借用了1MB,从堆或系统内存中借用,或者Java为线程分配任何特定的内存。你能帮我理解一下吗? 此外,我们是否有一个可视化(插件)运行时工具,可以以可理解的方式显示堆和堆栈的内容? 提前感谢。
我在做一个监控项目;我们有监控软件工作,并从服务器上回收指标。一切都很好,但是我们需要一些关于JVM内存使用细节的信息。我们有一些具有不同内存类型的列。我们需要知道这些是什么: 堆 非堆 用法 峰值 科尔 我们有所有这些列的最大值(HeapMax、NonHeapMax、UsageMax、PeakMax和CollMax),也有used(HeapUsed、NonHeapUsed、UsageUsed、P
主要内容:1.运行时数据区,3.Java堆,4.方法区(Method Area)1.运行时数据区 运行时数据区 Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分为若干个不同的数据区域。每个区域都有各自的作用。 分析 JVM 内存结构,主要就是分析 JVM 运行时数据存储区域。JVM 的运行时数据区主要包括:堆、栈、方法区、程序计数器等。而 JVM 的优化问题主要在线程共享的数据区中:堆、方法区。 1. 程序计数器 程序计数器(Program Counter
我有一个Java程序可以在Solaris 10 X86上运行,具有2GB物理内存和2GB交换。 该程序在64位Linux中运行良好,仅消耗约450MB内存。 然而,当它在Solaris中运行时,它总是报告OutOfMemoryError,我注意到在错误发生之前,它正试图使用 那么为什么JVM会尝试使用那么多虚拟内存呢?有没有办法告诉JVM不要使用那么多虚拟内存? 谢谢你。 编辑: 谢谢大家的意见!