在Java中创建的OutOfMemoryError对象在哪里

时间:2017-09-19 06:14:39

标签: java memory-management exception-handling jvm jvm-hotspot

当堆没有足够的内存来创建新对象时,会发生OutOfMemoryError。如果堆没有足够的内存,则创建OutOfMemoryError对象的位置。我想了解这一点,请指教。

2 个答案:

答案 0 :(得分:6)

当然,这是一种依赖于实现的行为。 HotSpot有一些堆内存对于普通分配是不可访问的,JVM可以用它来构造OutOfMemoryError。但是,由于Java允许任意数量的线程,因此任意数量的线程可能同时碰到墙,所以没有保证内存足以为每个实例构建一个独特的OutOfMemoryError实例。

因此,在整个会话期间持续存在的JVM启动时会创建紧急OutOfMemoryError实例,以确保即使没有剩余内存也可以抛出错误。由于实例将为遇到错误的所有线程共享,而实际上没有剩余内存,因此您将通过此错误将没有堆栈跟踪这一事实识别出这种无关的条件。

以下计划

ConcurrentHashMap<OutOfMemoryError,Integer> instances = new ConcurrentHashMap<>();

ExecutorService executor = Executors.newCachedThreadPool();
executor.invokeAll(Collections.nCopies(1000, () -> {
             ArrayList<Object> list = new ArrayList<>();
             for(;;) try {
                 list.add(new int[10_000_000]);
             } catch(OutOfMemoryError err) {
                 instances.merge(err, 1, Integer::sum);
                 return err;
             }
         }));
executor.shutdown();
System.out.println(instances.size()+" distinct errors created");
instances.forEach((err,count) -> {
    StackTraceElement[] trace = err.getStackTrace();
    System.out.println(err.getClass().getName()+"@"+Integer.toHexString(err.hashCode())
      +(trace!=null&&trace.length!=0? " has": " has no")+" stacktrace, used "+count+'x');
});

jdk1.8.0_65下与-Xmx100M一起运行并等了半分钟给了我

5 distinct errors created
java.lang.OutOfMemoryError@c447d22 has no stacktrace, used 996x
java.lang.OutOfMemoryError@fe0b0b7 has stacktrace, used 1x
java.lang.OutOfMemoryError@1e264651 has stacktrace, used 1x
java.lang.OutOfMemoryError@56eccd20 has stacktrace, used 1x
java.lang.OutOfMemoryError@70ab58d7 has stacktrace, used 1x

显示保留的内存可以用于构造四个不同的OutOfMemoryError实例(包括记录其堆栈跟踪所需的内存),而所有其他线程必须回退到保留的共享实例。

当然,不同环境的数字可能会有所不同。

答案 1 :(得分:4)

它由JVM本机生成,不受-Xmx或其他参数的限制。为您的程序保留的堆已用尽,而不是JVM可用的内存。