用Java创建的OutOfMemoryError对象在哪里 [英] Where is the OutOfMemoryError object created in Java

查看:72
本文介绍了用Java创建的OutOfMemoryError对象在哪里的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当堆没有足够的内存来创建新对象时,会出现OutOfMemoryError.如果堆没有足够的内存,则在哪里创建OutOfMemoryError对象.我想了解这一点,请告知.

An OutOfMemoryError occurs when the heap does not have enough memory to create new objects. If the heap does not have enough memory, where is the OutOfMemoryError object created. I am trying to understand this, please advise.

推荐答案

当然,这是与实现有关的行为. HotSpot具有一些普通分配无法访问的堆内存,JVM可以用来在其中构造OutOfMemoryError.但是,由于Java允许任意数量的线程,因此任意数量的线程可能会同时出现,因此没有保证该内存足以为它们每个构造一个不同的OutOfMemoryError实例.

Of course, this is an implementation-dependent behavior. HotSpot has some heap memory inaccessible for ordinary allocations, the JVM can use to construct an OutOfMemoryError in. However, since Java allows an arbitrary number of threads, an arbitrary number of threads may hit the wall at the same time, so there is no guaranty that the memory is enough for constructing a distinct OutOfMemoryError instance for each of them.

因此,在JVM启动时会创建一个紧急OutOfMemoryError实例,该实例在整个会话中持续存在,以确保即使实际上没有剩余的内存也可以引发该错误.由于实例将共享给所有遇到该错误的线程,而实际上没有剩余的内存,因此您将认识到这种无关紧要的情况,因为该错误将不再具有堆栈跟踪.

Therefore, an emergency OutOfMemoryError instance is created at the JVM startup persisting throughout the entire session, to ensure, that the error can be thrown even if there is really no memory left. Since the instance will be shared for all threads encountering the error while there’s really no memory left, you will recognize this extraneous condition by the fact that this error will have no stack trace then.

以下程序

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一起跑步并等待了半分钟,这给了我

running under jdk1.8.0_65 with -Xmx100M and waiting half a minute gave me

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实例(包括记录其堆栈跟踪所需的内存),而所有其他线程必须回退到保留的共享实例.

showing that the reserved memory could serve the construction of four distinct OutOfMemoryError instances (including the memory needed to record their stack traces) while all other threads had to fall back to the reserved shared instance.

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

Of course, numbers may vary between different environments.

这篇关于用Java创建的OutOfMemoryError对象在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆