我想限制JVM使用的最大内存.注意,这不仅仅是堆,我想限制此进程使用的总内存.
我已经研究了大多数可用的方法,以了解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和Size by nmon(两者都应该代表相同)告诉我这个过程是7530MB(或精确到7710952KB nmon).这是TOO不同于预期的最大值:2009MB以上的最大值,并且根据jmap和jstat的堆内存分配甚至没有达到其峰值(2048-OldSpace + 1534-Eden _ + _ Survivors).
top 还告诉我代码堆栈是36KB(公平,对于最初的catalina启动器),数据堆栈是7.3GB(代表其余的).
这个tomcat服务器实例是唯一一个在这台机器上运行的实例,并且一直存在一些不稳定性.需要每三天重启一次,因为机器有7647544k RAM可用,没有交换(出于性能原因).我为限制做了数学计算,并期望按照它们进行操作我看到它对于在机器上运行的所有其他服务都是一个相当不错的安全边际(除了ssh和top本身之外没有其他任何打扰):7468 - 5521 = 1947.这对于"安全边际"来说几乎是太多了.
所以,我想了解所有内存的使用位置,以及为什么不遵守限制.如果缺少任何信息,我很乐意提供.
我有一个Tomcat webapp,它代表客户端执行一些漂亮的内存和CPU密集型任务.这是正常的,是所需的功能.但是,当我运行Tomcat时,内存使用量会随着时间的推移而猛增至4.0GB以上,此时我通常会杀死该进程,因为它会破坏我在开发计算机上运行的所有其他内容:

我以为我无意中用我的代码引入了内存泄漏,但在用VisualVM检查后,我看到了一个不同的故事:

VisualVM将堆显示为占用大约一GB的RAM,这就是我设置它所做的事情CATALINA_OPTS="-Xms256m -Xmx1024".
根据VisualVM的说法,为什么我的系统认为这个过程占用了大量的内存,它几乎没有占用任何内容?
经过一番进一步的嗅探,我注意到如果在应用程序中同时运行多个作业,则内存不会被释放.但是,如果我等待每个作业完成,然后再向我BlockingQueue提供服务ExecutorService,那么内存将被有效回收.我该怎么调试呢?为什么垃圾收集/内存重用会有所不同?