我目前正在 Jetty 中运行 Grails 应用程序。它工作正常,但占用的内存比我想要的要多。htop 显示 Jetty 正在像这样运行:java -server -Xmx256m -Xms256m -Xmn96m -XX:MaxPermSize=64m -Djetty.home=/home/...
在我看来,Jetty 可能使用的最大内存应该是 256 + 64 = 320 MB 左右。相反,它看起来像这样:
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ 命令
6256 jetty 20 0 2747M 623M 13732 S 0.0 31.3 1:28.06/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java -server -Xmx256m -Xms256m -Xmn96m -XX:MaxPermSize=64m -Djetty。家=...
显然我不希望内存使用量正好是 320 MB,但它不应该接近吗?为什么它会是预期内存的两倍?如果有的话,当堆填满时,Java 不应该拒绝分配更多空间吗?
我试图清楚地了解 jmap 发生了什么,但一切对我来说都是正确的:
# jmap -heap 6256
正在附加到进程 ID 6256,请稍候...
调试器连接成功。
检测到服务器编译器。
JVM版本是23.7-b01
使用线程局部对象分配。
4 个线程的并行 GC
堆配置:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 268435456 (256.0MB)
新大小 = 100663296 (96.0MB)
MaxNewSize = 100663296 (96.0MB)
OldSize = 5439488 (5.1875MB)
新比率 = 2
幸存者比率 = 8
PermSize = 21757952 (20.75MB)
MaxPermSize = 67108864 (64.0MB)
G1HeapRegionSize = 0 (0.0MB)
堆使用:
PS年轻一代
伊甸空间:
容量 = 65208320 (62.1875MB)
使用 = 33343488 (31.798828125MB)
免费 = 31864832 (30.388671875MB)
51.13379396984924% 已使用
从太空:
容量 = 17170432 (16.375MB)
使用 = 0 (0.0MB)
免费 = 17170432 (16.375MB)
0.0% 已使用
到太空:
容量 = 18284544 (17.4375MB)
使用 = 0 (0.0MB)
免费 = 18284544 (17.4375MB)
0.0% 已使用
PS老一代
容量 = 167772160 (160.0MB)
使用 = 132604224 (126.46124267578125MB)
免费 = 35167936 (33.53875732421875MB)
79.03827667236328% 已使用
PS烫发一代
容量 = 67108864 (64.0MB)
使用 = 55899320 (53.30974578857422MB)
免费 = 11209544 (10.690254211425781MB)
83.29647779464722% 已使用
26872 个实习字符串,占用 2932096 个字节。
据我所知,perm gen 空间和 heap 空间都没有满。那么,这 400 MB 的内存是用来做什么的呢?我可以在我的 Grails 应用程序或 Jetty 中进行更改以减少它吗?
我过去曾在 Jetty 上运行 Grails 应用程序,但内存使用率很低。现在刚刚检查了一个,它使用了 220 MB 的内存,所以我不确定我做错了什么。
请您参考如下方法:
JVM 是一个本地程序,consumes native resources ,包括 native 内存。 native 内存是运行时进程可用的内存,与 Java 应用程序使用的 Java 堆内存不同。每个虚拟化资源(包括 Java 堆和 Java 线程)都必须与虚拟机运行时使用的数据一起存储在 native 内存中。
你也可以看看这个answer这很好地解释了这个主题。
这个thread展示一些关于如何使用 Java 泄漏 native 内存的好例子。
Jetty documentation也指这个题目。
如果您使用的是 JDK7,您可以使用 VisualVM buffer monitor plugin用于监视在垃圾收集堆之外分配的直接缓冲区。




