从GC日志来看,似乎在一段时间之后,年轻人和老年人之间的堆大小正在减小。
以下是日志中的三个条目。
{gc调用之前的堆= 5:
PSYoungGen总计44800K,已用44180K [0x18220000、0x1b420000、0x24a20000)
伊甸园空间38400K,已使用100%[0x18220000,0x1a7a0000,0x1a7a0000)
来自6400K空间,已使用90%[0x1ade0000,0x1b3853c8,0x1b420000)
到空间6400K,已使用0%[0x1a7a0000,0x1a7a0000,0x1ade0000)
PSOldGen总51200K,已用16K [0x0ba20000、0x0ec20000、0x18220000)
对象空间51200K,已使用0%[0x0ba20000,0x0ba24128,0x0ec20000)
PSPermGen总32768K,已用12417K [0x03a20000、0x05a20000、0x0ba20000)
对象空间32768K,已使用37%[0x03a20000,0x046406c0,0x05a20000)
1047.599:[GC [PSYoungGen:44180K-> 5990K(44032K)] 44197K-> 6006K(95232K),0.0046671秒]
gc调用后堆= 5:
PSYoungGen总计44032K,已用5990K [0x18220000、0x1b5a0000、0x24a20000)
伊甸园空间37632K,已使用0%[0x18220000,0x18220000,0x1a6e0000)
来自空间6400K,已使用93%[0x1a7a0000,0x1ad79990,0x1ade0000)
到空间7552K,已使用0%[0x1ae40000,0x1ae40000,0x1b5a0000)
PSOldGen总51200K,已用16K [0x0ba20000、0x0ec20000、0x18220000)
对象空间51200K,已使用0%[0x0ba20000,0x0ba24128,0x0ec20000)
PSPermGen总32768K,已用12417K [0x03a20000、0x05a20000、0x0ba20000)
对象空间32768K,已使用37%[0x03a20000,0x046406c0,0x05a20000)
}
{gc调用之前的堆= 174:
PSYoungGen总9728K,已用9666K [0x18220000、0x18d30000、0x24a20000)
伊甸园空间8640K,已使用99%[0x18220000,0x18a8fa58,0x18a90000)
来自空间1088K,已使用94%[0x18a90000,0x18b910f0,0x18ba0000)
到空间1344K,已使用0%[0x18be0000,0x18be0000,0x18d30000)
PSOldGen总计51200K,已使用21113K [0x0ba20000、0x0ec20000、0x18220000)
对象空间51200K,已使用41%[0x0ba20000,0x0cebe540,0x0ec20000)
PSPermGen总计32768K,已用12611K [0x03a20000、0x05a20000、0x0ba20000)
对象空间32768K,已使用38%[0x03a20000,0x04670fa0,0x05a20000)
26968.748:[GC [PSYoungGen:9666K-> 1271K(9920K)] 30780K-> 22465K(61120K),0.0025274秒]
gc调用后堆= 174:
PSYoungGen总9920K,已用1271K [0x18220000、0x18d50000、0x24a20000)
伊甸园空间8576K,已使用0%[0x18220000,0x18220000,0x18a80000)
来自1344K空间,使用了94%[0x18be0000,0x18d1dd00,0x18d30000)
到空间1408K,已使用0%[0x18a80000,0x18a80000,0x18be0000)
PSOldGen总计51200K,已使用21194K [0x0ba20000、0x0ec20000、0x18220000)
对象空间51200K,已使用41%[0x0ba20000,0x0ced29e0,0x0ec20000)
PSPermGen总计32768K,已用12611K [0x03a20000、0x05a20000、0x0ba20000)
对象空间32768K,已使用38%[0x03a20000,0x04670fa0,0x05a20000)
}
{gc调用之前的堆= 23195:
PSYoungGen总1536K,已用1372K [0x18220000、0x18440000、0x24a20000)
伊甸园空间896K,已使用100%[0x18220000,0x18300000,0x18300000)
来自640K空间,使用了74%[0x183a0000,0x184173e8,0x18440000)
到640K空间,已使用0%[0x18300000,0x18300000,0x183a0000)
PSOldGen总计6272K,已用4627K [0x0ba20000、0x0c040000、0x18220000)
对象空间6272K,已使用73%[0x0ba20000,0x0bea4d70,0x0c040000)
PSPermGen总32768K,已用12930K [0x03a20000、0x05a20000、0x0ba20000)
对象空间32768K,已使用39%[0x03a20000,0x046c0aa0,0x05a20000)
71908.146:[GC [PSYoungGen:1372K-> 533K(1536K)] 6000K-> 5423K(7808K),0.0107964秒]
gc调用后堆= 23195:
PSYoungGen总1536K,已用533K [0x18220000、0x18460000、0x24a20000)
伊甸园空间896K,已使用0%[0x18220000,0x18220000,0x18300000)
来自640K空间,已使用83%[0x18300000,0x18385438,0x183a0000)
到704K空间,已使用0%[0x183b0000,0x183b0000,0x18460000)
PSOldGen总计6272K,已用4890K [0x0ba20000、0x0c040000、0x18220000)
对象空间6272K,已使用77%[0x0ba20000,0x0bee6868,0x0c040000)
PSPermGen总32768K,已用12930K [0x03a20000、0x05a20000、0x0ba20000)
对象空间32768K,已使用39%[0x03a20000,0x046c0aa0,0x05a20000)
}
使用的(相关)JVM参数如下:
-服务器
-Xms600m
-Xss256k
-XX:+ UseParallelGC
-XX:+ PrintHeapAtGC
-XX:+ HeapDumpOnOutOfMemoryError
-Xloggc:verbose_gc.log
-Djavax.net.debug =无
-XX:+ PrintGC详细信息
-XX:+ PrintTenuringDistribution
-XX:+ PrintClassHistogram
-Xmx800m
-XX:NewRatio = 1
-XX:CompileThreshold = 1500
-XX:PermSize = 32m
-XX:MaxPermSize = 128m
当使用可视vm观察时,一个简单创建新线程的示例应用程序显示内存被过多线程消耗的假设(基于对堆栈内存与堆内存不同的理解)是错误的(年轻的和终身的)世代相传)。
对此行为有什么解释吗?
更新#1:
更正和更新:
上面的示例应用程序还包括一个随每个线程创建的数组对象。数组大小是总堆的重要部分。
在JDK 1.5中可以观察到此问题。
-R
最佳答案
实际上,这是JVM的正常行为。当JVM注意到您一段时间未使用某些已分配的HEAP内存时,它会假定您的应用程序运行时所用的内存少于您分配的容量,并且会减少垃圾回收期间堆的总大小(但绝不小于使用-Xms指定的最小堆大小)将内存释放回操作系统。
如果将来发现您的应用程序实际上需要使用更多的堆内存,则JVM将从OS保留更多的内存(直至使用-Xmx指定的最大堆大小)。
我曾经在某些Web应用程序中看到过这种情况,这似乎是正常现象。这样做的麻烦在于,当应用程序突然比平时需要更多的内存时,堆的减少会导致一些不需要的完整垃圾回收。
就我而言,堆大小的这种减少导致了世界各地的完整垃圾收集过多。我们通过使最小堆大小接近最大堆大小来解决了该问题。如果确实要避免此行为,则可以将最小堆大小设置为等于最大堆大小。
还要注意,线程堆栈空间占用的内存不算作堆IIRC的一部分。