4

我最近尝试激活垃圾优先垃圾收集器并对其进行评估。作为开始,我编写了这段代码,试图生成一个java.lang.OutOfMemoryError

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class G1Test {
  public static void floodMemory() {
    int i = 0;
    try {
      // allocate an array where we will just store a lot of java objects
      List<Date> l = new ArrayList<Date>();
      for (; i < 1051366050; i++) {
        l.add(new Date());
      }
    } catch (Throwable t) {
      System.err.println("Throwable in floodMemory!");
      System.out.println("i=" + i);
      t.printStackTrace();
    }
  }

  public static void main(String[] args) {
    try {
      System.out.println("Started memory flooding.");
      floodMemory();
      System.out.println("Sleeping.");
      Thread.sleep(Long.MAX_VALUE);
    } catch (Throwable t) {
      System.err.println("Throwable in main!");
      t.printStackTrace();
    }
  }
}

...我使用两种情况运行代码:

案例 1. 使用这些标志:-Xmx4096M -XX:+UseG1GC,我得到以下输出:

    开始内存泛滥。
    主要可投掷!
    java.lang.OutOfMemoryError:Java 堆空间
    在 com.siemens.scr.usi.experimental.G1Test.floodMemory(G1Test.java:14)
    在 com.siemens.scr.usi.experimental.G1Test.main(G1Test.java:26)

...这意味着臭名昭著的东西OutOfMemoryError被扔到了某个地方,但在 main 方法中被捕获了。

案例 2. 使用这个标志:-Xmx4096M,我得到这个输出:

Started memory flooding.
Throwable in floodMemory!
i=105136605
java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:242)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
    at java.util.ArrayList.add(ArrayList.java:440)
    at com.siemens.scr.usi.experimental.G1Test.floodMemory(G1Test.java:14)
    at com.siemens.scr.usi.experimental.G1Test.main(G1Test.java:26)
Sleeping.

...这意味着异常在我期望它被捕获的地方被捕获。

笔记:

  1. 该代码是纯实验性的,不遵循任何特定目的 - 只是为了观察行为。
  2. 该代码使用 Oracle JDK 1.7.0 更新 60、64 位在 Dell Precision M4700 上运行的 Windows 7 Enterprise 上运行。

问题是是否有人可以解释这种行为 - 找不到任何类似的帖子或任何错误报告(我的问题是缺乏一致性)。

4

1 回答 1

0

这只是一个理论,但它可能与垃圾收集设置没有任何关系,至少不是直接的:

在第一种情况下(-Xmx4096M -XX:+UseG1GC):OutOfMemoryError 可能已经在方法 floodMemory 中抛出,正如预期的那样,但是由于您已经准备好处于 OutOfMemory 状态,因此可能会抛出另一个 OutOfMemoryError在 floodMemory 方法的 catch 块中。System.err 命令可能会抛出第二个,这就是您看不到第一个输出的原因。然后,此错误会传播到 main 方法。

在第二种情况下,垃圾收集器可能已经能够释放足够的内存以供 System.err 执行并完成应用程序的其余部分。

同样,这只是一个理论。我尝试使用 Java 1.7 运行第一个案例,最终我的程序只是挂起,我没有看到抛出异常。

于 2014-07-16T20:13:49.327 回答