如何让PSOldGen扩展以容纳非常大的对象?
我有一个程序需要为一个非常大的对象分配堆空间,但我发现当空闲堆似乎比该大对象应该需要的多得多时,我会收到 OutOfMemoryException 。
这个测试程序演示了这个问题:
public class HeapTest {
public static void main(String[] args) {
final int size = Integer.parseInt(args[0]);
System.out.println(size >> 20);
final byte[] buf = new byte[size];
System.out.println(buf.length);
}
}
如果我将其运行为 java -Xmx40M -XX:+PrintGCDetails HeapTest 28000000
,我会得到以下输出:
26
[GC [PSYoungGen: 317K->176K(9216K)] 317K->176K(36544K), 0.0007430 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC [PSYoungGen: 176K->144K(9216K)] 176K->144K(36544K), 0.0004650 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen: 144K->0K(9216K)] [PSOldGen: 0K->115K(9216K)] 144K->115K(18432K) [PSPermGen: 2710K->2710K(21248K)], 0.0053960 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC [PSYoungGen: 0K->0K(9216K)] 115K->115K(36544K), 0.0002010 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen: 0K->0K(9216K)] [PSOldGen: 115K->112K(15104K)] 115K->112K(24320K) [PSPermGen: 2710K->2708K(21248K)], 0.0078150 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at HeapTest.main(HeapTest.java:5)
Heap
PSYoungGen total 9216K, used 476K [0x00000000ff2b0000, 0x0000000100000000, 0x0000000100000000)
eden space 7936K, 6% used [0x00000000ff2b0000,0x00000000ff327190,0x00000000ffa70000)
from space 1280K, 0% used [0x00000000ffa70000,0x00000000ffa70000,0x00000000ffbb0000)
to space 1280K, 0% used [0x00000000ffec0000,0x00000000ffec0000,0x0000000100000000)
PSOldGen total 27328K, used 112K [0x00000000fd800000, 0x00000000ff2b0000, 0x00000000ff2b0000)
object space 27328K, 0% used [0x00000000fd800000,0x00000000fd81c378,0x00000000ff2b0000)
PSPermGen total 21248K, used 2815K [0x00000000f3000000, 0x00000000f44c0000, 0x00000000fd800000)
object space 21248K, 13% used [0x00000000f3000000,0x00000000f32bff48,0x00000000f44c0000)
The array I'm attempts to create should be about 27344K, which稍微超过 PSoldGen 对象空间的大小。然而,未使用的总空间约为 54000K,几乎是我的阵列所需空间的两倍。由于我的(真实的)程序就地在数组上工作,它几乎不使用超出数组所需的任何内存,因此分配我需要的两倍的内存并且只使用其中的一半似乎很浪费。
有没有一种方法可以说服 JVM 让老一代的增长速度超过默认情况下的增长速度?
I have a program which needs to allocate heap space for one very large object, but I'm finding that I get OutOfMemoryException
s when there appears to be much more free heap than that large object should require.
This test program demonstrates the problem:
public class HeapTest {
public static void main(String[] args) {
final int size = Integer.parseInt(args[0]);
System.out.println(size >> 20);
final byte[] buf = new byte[size];
System.out.println(buf.length);
}
}
If I run it as java -Xmx40M -XX:+PrintGCDetails HeapTest 28000000
, I get the following output:
26
[GC [PSYoungGen: 317K->176K(9216K)] 317K->176K(36544K), 0.0007430 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC [PSYoungGen: 176K->144K(9216K)] 176K->144K(36544K), 0.0004650 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen: 144K->0K(9216K)] [PSOldGen: 0K->115K(9216K)] 144K->115K(18432K) [PSPermGen: 2710K->2710K(21248K)], 0.0053960 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC [PSYoungGen: 0K->0K(9216K)] 115K->115K(36544K), 0.0002010 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen: 0K->0K(9216K)] [PSOldGen: 115K->112K(15104K)] 115K->112K(24320K) [PSPermGen: 2710K->2708K(21248K)], 0.0078150 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at HeapTest.main(HeapTest.java:5)
Heap
PSYoungGen total 9216K, used 476K [0x00000000ff2b0000, 0x0000000100000000, 0x0000000100000000)
eden space 7936K, 6% used [0x00000000ff2b0000,0x00000000ff327190,0x00000000ffa70000)
from space 1280K, 0% used [0x00000000ffa70000,0x00000000ffa70000,0x00000000ffbb0000)
to space 1280K, 0% used [0x00000000ffec0000,0x00000000ffec0000,0x0000000100000000)
PSOldGen total 27328K, used 112K [0x00000000fd800000, 0x00000000ff2b0000, 0x00000000ff2b0000)
object space 27328K, 0% used [0x00000000fd800000,0x00000000fd81c378,0x00000000ff2b0000)
PSPermGen total 21248K, used 2815K [0x00000000f3000000, 0x00000000f44c0000, 0x00000000fd800000)
object space 21248K, 13% used [0x00000000f3000000,0x00000000f32bff48,0x00000000f44c0000)
The array I'm trying to create should be about 27344K, which slightly exceeds the size of the PSOldGen object space. However, the total unused space is about 54000K, which is almost twice what's needed for my array. Since my (real) program works on the array in-place, it uses barely any memory beyond what's required for the array, so allocating twice the memory I need and using only half of it seems wasteful.
Is there a way that I can convince the JVM to let the old generation to grow more than it seems able to by default?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以使用
NewRatio
、NewSize
、MaxNewSize
和SurvivorRatio
来调整Young Generation的大小strong>,从而间接地调整了老一代的大小。另外,如果您担心永久代使用过多内存,可以使用
MaxPermSize
命令行选项进行调整。请参阅使用 5.0 Java[tm] 虚拟机调整垃圾收集 了解更多详细信息,尤其是有关 一代。
例如,将最大年轻代大小设置为
10M
可以让您的示例程序成功运行:在我的机器上产生以下输出:
You can use
NewRatio
,NewSize
,MaxNewSize
andSurvivorRatio
to tune the size of Young Generation, thus indirectly also tuning the size of Old Generation.Also, if you are worried about Permanent Generation using too much memory, you can tune that with
MaxPermSize
command line option.See Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine for more details, especially the part about generations.
For example, setting the maximum Young Generation size to
10M
allows your sample program to run successfully:produces the following output on my machine: