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');
});
用-Xmx100M
在jdk1.8.0_65
下运行,等了半分钟给我
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.
相关文章