How to debug OutOfMemoryError

Hello,

I have recently updated my MicroEJ platform to add the network support.
I have tested this with a simple application that just do a DNS request and it works fine, but when I wanted to try it with my main application I got an OutOfMemoryError:

Exception in thread “main” java.lang.OutOfMemoryError
at ej.bon.Immortals.@M:0x808b138:0x808b148@
at ej.sni.PoolOfImmortalByteBuffers.@M:0x8085678:0x8085692@
at ej.sni.PoolOfReusableResources.@M:0x808acd4:0x808ad20@
at ej.sni.PoolOfLimitedReusableResources.@M:0x8085698:0x80856ce@
at ej.sni.PoolOfImmortalByteBuffers.@M:0x808aef0:0x808af04@
at com.is2t.support.net.NetworkResources.@M:0x809486c:0x8094892@
at com.is2t.support.net.NetworkResources.@M:0x80b7824:0x80b783c@
at java.lang.Thread.@M:0x80b60e0:0x80b60f0@
at java.lang.Thread.@M:0x80c0190:0x80c01a4@
at java.lang.Thread.@M:0x80c015c:0x80c0167@
VM END (exit code = 0)

I don’t really know how to debug this and why i need more memory. I also don’t know where to declare this extract memory.
Do you have some documentation or flow that could help me to debug this type of error?

Thanks for your help.

A.W.

Hello,

Can you please provide the decoded stack trace using Stack Trace Reader ?

https://docs.microej.com/en/latest/ApplicationDeveloperGuide/stackTraceReader.html

Thanks,

–Frédéric

Hi Fréderic,
Thanks for the hint, I have missed this stackTraceReader while reading the documentation.
Here is the trace decoded:

Exception in thread “main” java.lang.OutOfMemoryError
at ej.bon.Immortals.setImmortal(Unknown Source)
at ej.sni.PoolOfImmortalByteBuffers.newResource(PoolOfImmortalByteBuffers.java:25)
at ej.sni.PoolOfReusableResources.reserve(PoolOfReusableResources.java:62)
at ej.sni.PoolOfLimitedReusableResources.(PoolOfLimitedReusableResources.java:29)
at ej.sni.PoolOfImmortalByteBuffers.(PoolOfImmortalByteBuffers.java:21)
at com.is2t.support.net.NetworkResources.initialize(NetworkResources.java:88)
at com.is2t.support.net.NetworkResources.(NetworkResources.java:84)
at java.lang.Thread.execClinit(Unknown Source)
at java.lang.Thread.clinitWrapper(Thread.java:483)
at java.lang.Thread.callWrapper(Thread.java:449)
VM END (exit code = 0)

Thanks
A. W.

Accodring to the BON setImmortal documentation (Immortals), an OutOfMemoryError is thrown when the immortals heap is full.

You can update your immortals heap size using the Application Option: core.memory.immortal.size.

Ok, indeed this fixed the issue.
I update core.memory.immortal.size from 256 to over 35000.
Is there a way to print the size of the immortal heap during the application execution. I would like to size this heap as short as possible.

Thanks for your efficient help!
A.W.

Yes, you can retrieve the immortal heap usage by calling Immortals.freeMemory() right after a call to System.gc().

Here is a typical example of code:

		System.gc();
		long used = Immortals.totalMemory() - Immortals.freeMemory();
		System.out.println("Current Immortal Heap Usage = " + used + " (bytes)");

–Frédéric

Thanks Frederic,
That’s what I need.

Regards

A.W.

Increasing the heap size is a bad solution, 100% temporary, because you will hit the same issue if you get several parallel requests or when you try to process a bigger file.

This is a runtime error in Java which occurs when you allocate a new object in your application over a period of time continuously and the Garbage Collector (GC) cannot make space available to accommodate a new object, and the heap cannot be expanded further, which resulted this error.

Therefore you pretty much have the following options:

  • Find the root cause of memory leaks with help of profiling tools like MAT, Visual VM , jconsole etc. Once you find the root cause, You can fix this memory leaks.
  • Optimize your code so that it needs less memory, using less big data structures and getting rid of objects that are not any more used at some point in your program.

To avoid OutOfMemoryError, write high performance code:

  • Use local variables wherever possible.
  • Release those objects which you think shall not be needed further.
  • Avoid creation of objects in your loop each time.