Linux 上的 Java 内存使用情况

2022-09-04 22:57:42

我正在运行一些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线程堆栈,它是Linux的32位JVM上每个线程320k。同样,我使用 Psi-probe 来计算该特定 JVM 上的线程数,总数为 129 个线程。所以 129 + 320k = 42M

我读过NIO在堆外使用内存,但我们在应用程序中不使用NIO。

所以在这里,我已经计算了(我)想到的一切。我只占了“失踪”的170M中的60M。

我错过了什么?


答案 1

尝试使用增量垃圾回收器,使用 -Xincgc 命令行选项。它在整个GC工作中更具侵略性,并且有一个特别令人高兴的小异常:它实际上将一些未使用的内存交还给操作系统,这与默认和其他GC选择不同!这使得JVM消耗的内存要少得多,如果你在一台机器上运行多个JVM,这尤其好。以牺牲一些性能为代价 - 但您可能没有注意到它。incgc似乎有点秘密,因为没有人提起它......它已经存在了很长一段时间(甚至90年代)。


答案 2

Arnar,在JVM初始化过程中,JVM将分配由-Xmx和MaxPermSize指定的大小的内存(mmap或malloc),因此无论如何JVM将在JVM进程开始时为应用程序分配450 + 192 = 642m的堆空间。因此,用于应用程序的java堆空间不是537,而是其642m。所以现在如果你做计算,它会给你你丢失的记忆。希望它有帮助。