I have a server that handles requests via a socket and spawns a thread to handle each request.
Why do I get a
java.lang.OutOfMemoryError and what can I do to fix it?
Force a heapdump when the out of memory happens. See Can I force generation of a JVM crash log file?. Then use the tools listed there to narrow down the memory leak: Tool for analyzing large Java heap dumps
Type I: Out of heap space.
This is the most common error. It can be hard to track down because it involves understanding what objects are 'normal' and which objects should be released.
Creating unbounded amount of referenced objects. Creating objects that are thread specific but are referenced by one more global objects.
If you can reproduce the issue, running
Then analyze the heap file with
Type II: Out of process memory
If you have implemented JNI calls, or have objects created on your behalf by the JVM, which creates JNI objects, you can run out of process memory, which for a 32-bit process is 4 gig.
The process space of your running java process consists of:
-Xmx only controls the sizing of the JVM memory.
Type III: The garbage collector does not run
I have not found any reference to this situation in any web search. I think I have read every posting for solving
If you have a java program making JNI calls to native code, the garbage collector does not run while any thread is in a JNI call. Given a sufficient busy system, with two or more threads in a JNI call, it possible for the garbage collector to not run, ever.
The first instance was a long running JNI call which made a callback into java code to release the current object and fetch a new one. At each iteration, the amount of memory used grew and the unused objects did not get garbage collected.
The second instance was a test in which every spawned thread caused a JNI call. The code would run for a very long time, about an hour or so, but die with a
-Xloggc option showed periodic garbage collection for the first 4000 seconds until the number of concurrent threads running increased.
4055.330: [GC 4055.330: [ParNew: 147424K->12220K(147456K), 0.0073372 secs] 769563K->637289K(1294336K) icms_dc=0 , 0.0073809 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 18668.710: [GC 18668.710: [ParNew: 143289K->16384K(147456K), 0.0297121 secs] 768358K->651851K(1294336K) icms_dc=0 , 0.0297604 secs]
[Update 7 Jun 2014] In one instance I found this answer Memory leak when calling java code from C using JNI fixed the issue. The local java memory is assigned to the C stack even if it's allocated in java, because it's made from inside a JNI call. Specifically, I wrapped the back call to java with PushLocalFrame()/PopLocalFrame() to fix the issue.