Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
407 views
in Technique[技术] by (71.8m points)

memory management - Where is the OutOfMemoryError object created in Java

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.

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.

The following program

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');
});

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

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...