X

Poonam Bajaj's Blog

  • April 27, 2017

HotSpot JVM throwing OOM even when there is memory available

Poonam Parhar
Consulting Member of Technical Staff

I was recently asked a question that why my Java application runs out of Java Heap when there is still so much memory available to use?

Here is the question in detail - I am running my application with -Xmx1600m but the logs show that it runs out of memory without fully using the 1600mb.

2017-03-21T13:15:39.478+0000: 289274.599: [Full GC [PSYoungGen: 338944K->0K(425472K)] [ParOldGen: 1092073K->1055276K(1092096K)] 1431017K->1055276K(1517568K) [PSPermGen: 493920K->493889K(494592K)], 1.1709840 secs] [Times: user=5.06 sys=0.00, real=1.18 secs]
...
2017-03-21T13:19:50.517+0000: 289525.638: [Full GC [PSYoungGen: 322035K->0K(364544K)] [ParOldGen: 1092088K->1091814K(1092096K)] 1414124K->1091814K(1456640K) [PSPermGen: 494764K->494163K(495104K)], 2.5423990 secs] [Times: user=15.30 sys=0.00, real=2.54 secs]
The maximum capacity of the heap sometimes goes up to 1517568K and sometimes stays at 1456640K. Why does it not use the whole 1600mb?

Well, the short answer is that the rest of the unaccounted space is for one of the survivor spaces.

Long answer: Young generation is composed of Eden and 2 survivor spaces - From and To. Out of these only 'Eden' and 'From' space are available for allocations. 'To' is kept free to be used for copying surviving objects and is omitted while reporting the Young generation capacity.

Let's take a look at another example where I run a simple program that allocates extensively and runs out of the Java Heap. I run that program with the following options:
java -XX:+PrintGCDetails -Xmx60m -XX:MaxNewSize=20m TestProgram
...<snip>...
[Full GC (Ergonomics) [PSYoungGen: 15360K->15360K(17920K)] [ParOldGen: 40464K->40464K(40960K)] 55824K->55824K(58880K), [Metaspace: 2723K->2723K(1056768K)], 0.1519409 secs] [Times: user=0.50 sys=0.00, real=0.15 secs]
[Full GC (Ergonomics) [PSYoungGen: 15360K->15360K(17920K)] [ParOldGen: 40465K->40465K(40960K)] 55825K->55825K(58880K), [Metaspace: 2723K->2723K(1056768K)], 0.1196922 secs] [Times: user=0.41 sys=0.00, real=0.12 secs]
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
        at TestProgram.main(TestProgram.java:15)[Full GC (Ergonomics) [PSYoungGen: 15360K->0K(17920K)] [ParOldGen: 40468K->324K(30720K)] 55828K->324K(48640K), [Metaspace: 2748K->2748K(1056768K)], 0.0072977 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
I had the heap size configured at 60MB but the total capacity of the Java heap from the above logs is only 58880K. YoungGen:17920K + OldGen:40960K = Total:58880K. Where is 60*1024K-58880K = 2560K?

Now, if we look at the heap usage details:
Heap
 PSYoungGen      total 17920K, used 307K [0x00000000fec00000, 0x0000000100000000, 0x0000000100000000)
  eden space 15360K, 2% used [0x00000000fec00000,0x00000000fec4ce70,0x00000000ffb00000)
  from space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 30720K, used 324K [0x00000000fc400000, 0x00000000fe200000, 0x00000000fec00000)
  object space 30720K, 1% used [0x00000000fc400000,0x00000000fc4511e0,0x00000000fe200000)
 Metaspace       used 2755K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 301K, capacity 386K, committed 512K, reserved 1048576K  

Capacity of PSYoungGen:17920K = eden:15360K + from:2560K

It does not include the 'To' survivor space.

Join the discussion

Comments ( 1 )
  • Fairoz Thursday, May 11, 2017
    Very simple and nicely explained
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha