Friday, June 9, 2006

2811.aspx

How to fix "java.lang.OutOfMemoryError: unable to create new native thread"

I recently came across this exception on a couple of java systems that use many threads  java.lang.OutOfMemoryError: unable to create new native thread. The strange thing was that the JVM had been assigned a lot of memory (1.5GB) and that it had at least half the memory available. Michele found this article that points out that the more memory you give to the JVM the more likely you are to get java.lang.OutOfMemoryError: unable to create new native thread exceptions when you have many threads.


Which makes perfect sense when you think about it. Each 32 bit process on Windows has 2GB "available" memory as 2GB is reserved to Windows. In my case the JVM grabbed 1.5 GB leaving 500MB. Part of the 500MB was used to map system dlls etc in memory so less than 400 MB was left. Now to the crucial point: When you create a thread in java it creates a Thread object in the JVM memory but it also creates a operating system thread. The operating system creates the thread with a thread stack in the 400MB that is left, not in the 1.5 GB allocated in the JVM. Java 1.4 uses a default stack size of 256kb but Java 1.5 uses a 1MB stack per thread. So, in the 400MB left to process I could only generate ~400 threads. Absurd but true: to create more threads you have to reduce the memory allocated to the JVM. Another option is to host the JVM in your own process using JNI.


This formula gives a decent estimate for the number of threads you can create: 
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads


For Java 1.5 I get the following results assuming that the OS reserves about 120MB:
1.5GB allocated to JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads
1.0GB allocated to JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads


Java 1.4 uses 256kb for the thread stack which lets you create a lot more threads:
1.5GB allocated to JVM: ~1520 threads
1.0GB allocated to JVM: ~3520 threads


I have not tried the 3GB switch but it should in theory let you create more threads.

13 comments:

  1. I'd correct your numbers with the followings that seem to me more correct.

    JVM and OS use a more likely 150MB of Memory and the memory allocation of the Jvm is the sum of the Heap Allocation and of the Perm Size. The first can be fixed using the -Xms and -Xmx options, the second with the -XX:PermSize and -XX:MaxPermSize (default from 32MB to 64MB depending on JVM version).

    ReplyDelete
  2. Hi,



    When i start my thread process, it gets started. At the same time, its creating a file startthread.err with the content as

    "java.lang.OutOfMemoryError"



    Can someone please help me on this ?

    ReplyDelete
  3. Wonder why people are not using 64 bit OS and 64 bit JVM.

    If you require more threads and memory switch to 64 bit version.

    That is the best solution.

    ReplyDelete
  4. @Prem: I work for a very conservative, very big US company where the company standard is still xp/ie6/32bit ... it's really crappy. That brought me to this blog, my eclipse kept dying on me. I guess this should fix it.

    ReplyDelete
  5. @Anonymous: did changing startup parameters fix the issue? If not; how much physical memory does the machine have and how much memory are you requesting?

    ReplyDelete
  6. Very useful information in fixing the error ...

    Thanks for providing the valuable information

    ReplyDelete
  7. what is happening when this error occurs on a 64-bit machine. Is it just using up the entire memory space?

    ReplyDelete
  8. It's using up the entire memory space allocated to the process which could be very different from the total available memory on the machine

    ReplyDelete
  9. Thanks for this great article..

    ReplyDelete
  10. I have the same error on 64-bit machine. There are 2 tomcats running there. The first one takes 3Gb of heap and the second one - 2Gb.
    Error happened in the second tomcat. I thinks that 2 or more tomcats on the same server affects each other and that's why I get this error.
    What do you think?
    And could someone clarify this post:
    >It's using up the entire memory space allocated to the process >which could be very different from the total available memory on >the machine
    Is my calculation correct? (I ignored PemGen memory and OS memory)
    total 8Gb - 3Gb (1jvm) - 2Gb (2jvm) = 3Gb left for stack.
    Thanks in advance.

    ReplyDelete
  11. Hey Egil, If you are still alive. Do you know if the thread limits on your calculations are created threads or active threads. I mean do threads that have grefully finished also count towards the limit?

    ReplyDelete
  12. I am still alive :-)

    I don't know, but I would guess that all threads that have been created and have not been garbage collected count towards the limit.

    ReplyDelete
  13. For those seeing this on Linux with a 64-bit version of JVM, the original post only makes sense on 32-bit JVM's.

    Check out this article:
    https://www.java67.com/2016/10/javalangoutofmemoryerror-unable-to-create-new-native-thread-in-java-solution.html

    To see the allowed native limit on # threads:
    > ulimit -a | grep "max user proc"
    max user processes (-u) 256


    To see how many thread you're actually using (across all JVM instances):
    ps -eLF | grep java | wc -l
    227

    Per the articles recommendation, you need to bump up the limit. I did the following:
    sudo bash
    ulimit -u 2048

    ReplyDelete