如何让PSOldGen扩展以容纳非常大的对象?

发布于 2024-10-04 09:54:26 字数 2348 浏览 0 评论 0原文

我有一个程序需要为一个非常大的对象分配堆空间,但我发现当空闲堆似乎比该大对象应该需要的多得多时,我会收到 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 OutOfMemoryExceptions 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

聽兲甴掵 2024-10-11 09:54:26

您可以使用NewRatioNewSizeMaxNewSizeSurvivorRatio来调整Young Generation的大小strong>,从而间接地调整了老一代的大小。

另外,如果您担心永久代使用过多内存,可以使用MaxPermSize命令行选项进行调整。

请参阅使用 5.0 Java[tm] 虚拟机调整垃圾收集 了解更多详细信息,尤其是有关 一代

例如,将最大年轻代大小设置为10M可以让您的示例程序成功运行:

java -Xmx40M -XX:+PrintGCDetails -XX:MaxNewSize=10M HeapTest 28000000

在我的机器上产生以下输出:

26
28000000
Heap
 par new generation   total 9216K, used 1499K [106810000, 107210000, 107210000)
  eden space 8192K,  18% used [106810000, 106986ed0, 107010000)
  from space 1024K,   0% used [107010000, 107010000, 107110000)
  to   space 1024K,   0% used [107110000, 107110000, 107210000)
 concurrent mark-sweep generation total 30720K, used 27343K [107210000, 109010000, 109010000)
 concurrent-mark-sweep perm gen total 21248K, used 4501K [109010000, 10a4d0000, 10e410000)

You can use NewRatio, NewSize, MaxNewSize and SurvivorRatio 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:

java -Xmx40M -XX:+PrintGCDetails -XX:MaxNewSize=10M HeapTest 28000000

produces the following output on my machine:

26
28000000
Heap
 par new generation   total 9216K, used 1499K [106810000, 107210000, 107210000)
  eden space 8192K,  18% used [106810000, 106986ed0, 107010000)
  from space 1024K,   0% used [107010000, 107010000, 107110000)
  to   space 1024K,   0% used [107110000, 107110000, 107210000)
 concurrent mark-sweep generation total 30720K, used 27343K [107210000, 109010000, 109010000)
 concurrent-mark-sweep perm gen total 21248K, used 4501K [109010000, 10a4d0000, 10e410000)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文