Where is the OutOfMemoryError object created in Java
Asked Answered
R

2

9

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.

Rhodie answered 19/9, 2017 at 6:14 Comment(1)
excellent interview question IMO - but I would have failed it. thank you for posting itNeva
D
11

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.

Daudet answered 19/9, 2017 at 11:2 Comment(0)
B
5

It's generated natively by the JVM, which isn't limited by -Xmx or other parameters. The heap reserved for your program is exhausted, not the memory available for the JVM.

Byng answered 19/9, 2017 at 6:20 Comment(2)
Thank you. Well this was one of the interview questions asked to me in an interview.Rhodie
Actually, it’s slightly more complicatedDaudet

© 2022 - 2024 — McMap. All rights reserved.