我已经研究了大多数可用的方法,以找出java进程实际使用的内存量。 到目前为止,我可以说我知道分配的总内存可能是以下一项或多项:
但是结果与linux告诉我的结果太不一样了,我发现任何可用于获取java进程内存消耗的方法。
在我的例子中,它是在Ubuntu 11.10 x86_64机器上运行的Tomcat实例,JVM 1.6_u26 64位,ps -ALcf | grep org.apache.catalina.startup.Bootstrap | wc -l
告诉我运行了145个线程或进程,将所有线程或链接进程链接到同一根进程( Tomcat)的
所有总结应该给我总的最大记忆
(4096MB)+(1024MB)+(256MB)+ 145 *(1024KB)= 5521MB。
jmap -heap PID
告诉我的内容,ManagementFactory.memoryMXBean.(heapMemoryUsage + nonHeapMemoryUsage).getCommitted()
告诉我的内容以及上面的理论值都是配对。
现在到linux方面,top
和nmon
都告诉我这个过程分配的ResidentMemory是5.8GB - >大约5939,2MB。但我也知道这只是内存的一部分,即RAM内存的一部分。 VIRT top
和大小nmon
(两者都应该代表相同)告诉我这个过程是7530MB(或nmon
精确到7710952KB)。
这与预期的最大值不同: 2009MB高于最大值,并且根据jmap和jstat,堆内存分配甚至没有达到峰值(2048-OldSpace + 1534-Eden _ + _ Survivors)。
top
还告诉我代码堆栈是36KB(公平,对于初始的catalina启动器),数据堆栈是7.3GB(代表其余的)。
这个tomcat服务器实例是唯一一台在这台机器上运行的实例,并且一直存在一些不稳定性。需要每三天重启一次,因为机器有7647544k RAM可用,没有交换(出于性能原因)。我为限制做了数学运算,并期望按照它们的过程我看到它是一个非常好的安全边缘,留给机器上运行的所有其他服务(除了ssh和top本身之外没有任何一个应该打扰):7468 - 5521 = 1947.对于“安全边际”而言,这几乎是太多了。
所以,我想知道所使用的内存在哪里,为什么不遵守限制。如果缺少任何信息,我很乐意提供。
答案 0 :(得分:5)
这是一个very detailed article on how the JVM allocates and manages memory,根据您在问题中的假设,它并不像您预期的那样简单,值得全面阅读。
许多实现中的ThreadStack大小具有最小限制,这些限制因操作系统而有时因JVM版本而异;如果将限制设置为低于JVM或OS的本机操作系统限制,则会忽略threadstack设置(有时必须设置ulix on * nix)。其他命令行选项以相同的方式工作,当提供的值太小时,默认默认为更高的值。不要假设传入的所有值都代表实际使用的值。
类加载器和Tomcat有不止一个,占用了大量内存,而这些内存很难被记录下来。 JIT占用了大量的内存,随着时间的推移交易空间,这在大多数情况下是一个很好的交易。
你引用的数字非常接近我的期望。
答案 1 :(得分:3)
虚拟内存是使用的地址空间量,我不会太担心你有64位应用程序。驻留者是实际使用的主存储器的数量。
您可以添加到列表中
您可以执行pmap
向您显示正在使用多少地址空间。
BTW:由于内存映射文件,我的进程显示640G VIRT在顶部。它可能比居民大小高很多。 ;)