Jim*_*ski 4 java garbage-collection permgen
我正在使用JVM进行科学应用.我的过程的第一步是将大量数据加载到小double[]数组中(大图中每个节点的48个元素数组).早在我发现我是否有足够的内存来加载它们之前很久,Java就渐渐减速了,jvisualvm告诉我这是因为几乎所有的CPU时间花在了垃圾收集上:

第一分钟左右就可以了:"used heap"(右图)随着它的增长而上下跳跃,因为有些对象是临时的(我在Scala中写过),而且有些对象是永久性的.然而,在那之后,数据加载停止,因为垃圾收集器显然一遍又一遍地检查相同的对象(左图).它必须期望它们超出范围,但我将它们放在范围内,因为我想将它们用于我的分析.
我知道垃圾收集器根据生存的可能性将对象放在不同的世代中.第一代包含最近创建并可能很快死亡的对象; 后世逐渐更有可能长寿.如果我的对象在第一代中是错误的,有没有办法告诉垃圾收集器他们应该在下一代?我知道我会保留它们 - 我怎么能告诉垃圾收集器?
虽然我希望这些物体处于更加永久的一代,但PermGen太过分了:经过几十分钟的处理后,它们最终会死亡.(我想在Hadoop reducer中使用它,在没有新JVM的情况下,可能会在不同的数据块之后使用它.)
注意:我正在使用Sun HotSpot VM:
% java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
Run Code Online (Sandbox Code Playgroud)
更正(对于上一个编辑):更改-Xmx 确实会更改饱和点,但是-Xmx如果在-jar参数之后传递,则Java显然会忽略命令行参数.就是这样
java -Xmx2048 -jar MyJarFile.jar
Run Code Online (Sandbox Code Playgroud)
而不是
java -jar MyJarFile.jar -Xmx2048
Run Code Online (Sandbox Code Playgroud)
因此,我错误地诊断了关于最大堆的行为,并且指向该-Xmx标志的所有答案都是有效的.
我描述的饱和点发生在"堆大小"(右图上的橙色)达到所选-Xmx限制时,"堆大小"总是约为"已用堆"的1.6倍(右图中的蓝色),除非您明确设置带" -XX:NewRatio或"的"旧"代的大小-XX:OldSize.这些也需要在-jar论证之前,并且它们提供了很多控制.
除非你的堆接近饱和状态,否则GC不应该在螺旋中调用它自己.您需要增加最大堆大小(-Xmx) - 从接近预期保留期的2倍开始.您还可以使用CMS收集器,它可以改善大型终端组的情况.您也可能需要手动调整新一代,因为老一代不需要定期扫描.
您还可以考虑使用NIO直接ByteBuffers.虽然它们是为更高效的I/O操作而设计的,但它们对于长寿命和宽存储器阵列来说是一个合理的选择.