我正在运行一大堆Java应用程序服务器,它们都在CentOS 5.5 Linux之上运行最新版本的Tomcat 6和Sun的Java 6。每个服务器都运行多个Tomcat实例。
我正在设置-Xmx450m -XX:MaxPermSize = 192m参数来控制堆和permgen增长的大小。这些设置适用于所有Java应用程序服务器上的所有Tomcat实例,总共大约70个Tomcat实例。
以下是Psi-probe
报告的其中一个Tomcat实例的典型内存使用情况Eden = 13M
Survivor = 1.5M
Perm Gen = 122M
Code Cache = 19M
Old Gen = 390M
Total = 537M
然而,CentOS报告这个特定进程的RAM使用率为707M(根据RSS),这使得170M的RAM下落不明。
我知道JVM本身和它的一些依赖库必须加载到内存中,所以我决定启动pmap -d来查找它们的内存占用。 根据我的计算,约占17M。
接下来是Java线程堆栈,在32位JVM for Linux上每个线程320k。 同样,我使用Psi-probe来计算特定JVM上的线程数,总计为129个线程。所以129 + 320k = 42M
我已经读过NIO使用堆外的内存,但是我们的应用程序中没有使用NIO。
所以在这里我已经计算了(我的)头脑中的一切。而且我只占了“失踪”170M的60M。
我错过了什么?
答案 0 :(得分:3)
尝试使用增量垃圾收集器,使用-Xincgc命令行选项。 它在整个GC工作中更具攻击性,并且有一个特别快乐的小异常:它实际上将一些未使用的内存交还给操作系统,这与默认和其他GC选择不同! 这使得JVM消耗更少的内存,如果您在一台机器上运行多个JVM,这尤其有用。牺牲一些性能 - 但你可能不会注意到它。 incgc似乎是一个小秘密,因为没有人提起它......它已经存在了(甚至90年代)。
答案 1 :(得分:2)
Arnar,在JVM初始化过程中,JVM将分配由-Xmx和MaxPermSize指定的大小的内存(mmap或malloc),因此无论如何JVM将在JVM进程开始时为应用程序分配450 + 192 = 642m的堆空间。所以应用程序的java堆空间不是537,而是它的642m。所以现在如果你进行计算,它会给你缺少的内存。希望它有帮助。
答案 2 :(得分:1)
Java预先分配尽可能多的虚拟内存,但是驻留方将是您实际使用的数量。注意:许多库和线程都有自己的头脑,虽然你不使用直接内存,但这并不意味着底层系统都没有。例如如果你使用NIO,它将使用一些直接内存,即使你使用堆ByteBuffers。
最后,100 MB的价值约为8英镑。可能不值得花太多时间担心它。
答案 3 :(得分:0)
不是直接的答案,但是,您是否还考虑过托管multiple sites within the same Tomcat instance?这可以节省一些内存,但会牺牲一些额外的配置。
答案 4 :(得分:0)
Arnar,JVM也是mmap的所有正在使用的jar文件,它们将使用NIO并将为RSS做出贡献。我不相信上述任何测量都会考虑到这些因素。你偶然会有大量的大型jar文件吗?如果是这样,那些用于那些的页面可能是你遗失的内存。