If you are working with Java, I bet you are well aware about
OutOfMemoryError. But did you
know that there are 4 different conditions when OutOfMemoryError
is being thrown in Oracle’s HotSpot JVM? These conditions can be distinguished
by message provided by exception.
OutOfMemoryError: Java heap space
This is probably most common case for out of memory error.
It indicates that heap space is not large enough to hold object created by
application. To be precise, this exception is thrown if, after last full GC
cycle, free space in heap is below 2% (can be configured via –XX:GCHeapFreeLimit=p JVM option).
Normally you either have to increase JVM heap size or fix
memory leak in your application to remedy this.
OutOfMemoryError: GC overhead limit exceeded
This problem is trickier. It means that GC is spending “too
much” time cleaning memory. Portion of free space may be above 1%, but process
is spending 50 times more time managing memory than actually executing application
code. Threshold can be tweaked via -XX:GCTimeLimit=p
JVM option, default is 2% (1/50). Usually if you will increase heap size
problem will go away. But this error may also indicate that heap is badly
configured, i.e. young space is too small for application.
OutOfMemoryError: PermGen space
As you may know, HotSpot JVM is using special memory space
for certain internal structures – permanent space. Despite its name object from
permanent space could be collected (name is just a historic artifact). But you
may run out of memory in perm space same way as you can in normal heap. Thing
which may affect permanent space usage are
- loading/generating classes and creating with class loaders,
- reflection,
- calling String.intern() method.
Permanent space does not count to application heap size. If
you need to resize it, use –XX:MaxPermSize=s
JVM option.
OutOfMemoryError: Direct buffer memory
All previous types of OOME were indicating that GC failed to
free memory for new Java object (i.e. they are thrown as result of GC cycle). This
last type of OOME is different. Since Java 1.5, JVM have API to manage memory
outside of heap. Out of heap memory is not a subject for garbage collection,
but is also limited. Capacity of off heap memory pool is configured via –XX:MaxDirectMemorySize=s JVM option.
My statement about off heap memory not being garbage collected is only
partially true. Off heap memory blocks are deallocated in ByteBuffer class
finalizer so garbage collection of heap is also driving reclamation of
associated off-heap memory.
Nice and concise post.
ReplyDeleteSome folks tend to increase heap size blindly, whenever they encounter OOM.
Now I can point them here so they understand how OOMs can be different. And may indicate different problems, many of which won't be addressed with -Xmx.
(also IIRC direct memory is a part of NIO which is @since 1.4)
I think I have seen an OutOfMemoryError when trying to launch a native thread.
ReplyDeletethank you
ReplyDelete