Tuesday, December 21, 2010

java.lang.OutOfMemoryError

A java.lang.OutOfMemoryError is a subclass of java.lang.VirtualMachineError that is thrown when the Java Virtual Machine is broken or has run out of resources that are necessary to continue the operation of the Java Virtual Machine. Obviously, memory is the exhausted resource for a java.lang.OutOfMemoryError, which is thrown when the Java Virtual Machine cannot allocate an object due to memory constraints.

Occasionally we will meet OOME in QA or development environment, which is an error and JVM will stop running. Usually we can tell if OOME is from java heap or native memory from the error message. There are a lot of blogs/articles discussing this area, and from Google I found these articles are simple and easy to understand.
These are the list of OutOfMemoryErrors a typical java application can see:
  • java.lang.OutOfMemoryError: Perm Space 
    •  SUN JVM has one but Jrockit doesn't have an allocated permspace
    • -XX:MaxPermSize -XX:PermSize
  • java.lang.OutOfMemoryError: Java heap space 
    • jmap, jhat,  YourKit, Jprofiler (heap dump)
    • -Xms128m -Xmx1024m
  • java.lang.OutOfMemoryError: unable to create new native thread 
    • The java process size has reached its limit (OS tries to reserve space for thread stack within process address space)
    • -Xss512k
  • java.lang.OutOfMemoryError: GC overhead limit exceeded 
    • JVM took too long to free up memory during its GC process. This error can be thrown from the Parallel or Concurrent collectors.
    • -XX:-UseGCOverheadLimit
    •  The parallel collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown. This feature is designed to prevent applications from running for an extended period of time while making little or no progress because the heap is too small. If necessary, this feature can be disabled by adding the option -XX:-UseGCOverheadLimit to the command line.
  • java.lang.OutOfMemoryError: requested xxxx bytes for Chunk::new. Out of swap space
    • The process could not allocate memory as the virtual memory was full
    • The solution is to reduce the amount of heap memory you have allocated.
  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    • There is a memory request for an array but that's too large for a predefined limit of a virtual machine
    • We need to check the source code to make sure that there's no huge array created dynamically or statically. 
Side note: Another setting you may want to check on is the system ulimit setting. The ulimit setting controls the limit on how many file handles a single process can have open. Since the unix philosophy is to treat nearly everything as a file, this is trickier than it seems. Running out of file handles can be reported as an OutOfMemory error, which may take a while to figure out. Most flavors of unix have a reasonably high default ulimit these days, but just in case, check.

2 comments:

  1. Some one commented about gc over limit case:

    Use a more agressive GC methodology. This has been a saver in several situation. Remove the -XX:+UseParallelGC directive and use the -XX:+UseConcMarkSweepGC instead.

    I have also used other tweaks before including playing with the young/new/old ratios. Before going there profiling GC memory using open source tools such as GCViewer has been helpful.

    ReplyDelete