Fix JMeter java.lang.OutOfMemoryError: unable to create new native thread. Tune OS ulimit, kernel.pid_max, JVM stack size (-Xss), and thread scaling.
java.lang.OutOfMemoryError: unable to create new native thread in JMeter
Section titled “java.lang.OutOfMemoryError: unable to create new native thread in JMeter”Symptom
Section titled “Symptom”When ramping up to hundreds or thousands of threads in a JMeter test plan, the test suddenly halts or crashes with an unrecoverable JVM fatal error in the console or jmeter.log:
java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:717) at org.apache.jmeter.threads.ThreadGroup.start(ThreadGroup.java:310) at org.apache.jmeter.engine.StandardJMeterEngine.run(StandardJMeterEngine.java:490)New virtual users fail to spawn, and the JMeter process may become unresponsive or terminate immediately.
Quick diagnosis (TL;DR)
Section titled “Quick diagnosis (TL;DR)”This error is not caused by running out of Java Heap memory (-Xmx). It occurs when the Java Virtual Machine requests the underlying operating system kernel to allocate a new OS-level native thread, and the OS denies the request because the OS user process limit (ulimit -u), system PID limit (kernel.pid_max), or available native RAM for thread call stacks has been exhausted.
Common causes
Section titled “Common causes”| Cause | Layer | Why it happens |
|---|---|---|
Linux user process limit (ulimit -u) | OS | Default nproc limit (often 1024 or 4096) reached by Java and background OS tasks |
| Kernel PID limit | OS | System-wide /proc/sys/kernel/pid_max or /proc/sys/vm/max_map_count cap reached |
Large JVM thread stack size (-Xss) | JVM | Default stack size (1MB per thread) consumes all physical native RAM outside heap |
| Oversized single-instance thread count | JMeter Plan | Attempting to spawn 5,000+ threads on a single load injector machine |
| Thread leaks in plugins or Groovy | Custom Code | Third-party plugins or scripts spawning unmanaged new Thread() instances |
Fix (ordered)
Section titled “Fix (ordered)”1. Increase Linux OS User Process & File Descriptor Limits
Section titled “1. Increase Linux OS User Process & File Descriptor Limits”On Linux load injector machines, edit /etc/security/limits.conf:
# Add at the bottom of /etc/security/limits.conf* soft nproc 65535* hard nproc 65535* soft nofile 65535* hard nofile 65535root soft nproc 65535root hard nproc 65535Verify active limits in your current terminal session:
ulimit -u # max user processes (should show 65535)ulimit -n # max open files (should show 65535)2. Increase System PID and Memory Map Limits
Section titled “2. Increase System PID and Memory Map Limits”Configure Linux kernel sysctl parameters:
# Check current PID capacitysysctl kernel.pid_maxsysctl vm.max_map_count
# Temporarily increase limitssudo sysctl -w kernel.pid_max=4194304sudo sysctl -w vm.max_map_count=262144
# Make permanent in /etc/sysctl.confecho "kernel.pid_max = 4194304" | sudo tee -a /etc/sysctl.confecho "vm.max_map_count = 262144" | sudo tee -a /etc/sysctl.confsudo sysctl -p3. Tune JVM Thread Stack Size (-Xss)
Section titled “3. Tune JVM Thread Stack Size (-Xss)”In Java, each thread receives a dedicated native memory stack outside the heap. By default, 64-bit JVMs allocate 1MB per thread stack. If you run 2,000 threads, thread stacks alone consume 2GB of native RAM.
Reduce thread stack size in your JMeter launch environment:
# Set -Xss to 256k or 512k in bin/jmeter or environment variablesexport JVM_ARGS="-Xms4g -Xmx4g -Xss256k"jmeter -n -t test.jmx -l results.jtl -j jmeter.logOn Windows, edit bin/jmeter.bat or pass:
set JVM_ARGS=-Xms4g -Xmx4g -Xss256kjmeter.bat -n -t test.jmx -l results.jtl4. Optimize Thread Sizing (Little’s Law)
Section titled “4. Optimize Thread Sizing (Little’s Law)”Before scaling to thousands of threads, check if high thread counts are truly necessary. Many engineers add threads because responses are slow:
Threads = Target RPS × Average Response Time (seconds)If your target is 500 RPS and the server responds in 100ms (0.1s), you only need 50 threads, not 2,000. Use the Thread Calculator to calculate optimal concurrency.
5. Scale Out Horizontally with Distributed Testing
Section titled “5. Scale Out Horizontally with Distributed Testing”When a single machine reaches hardware or kernel limitations (typically ~1,500–2,500 threads per modern server depending on test complexity), distribute the load across multiple JMeter server instances (distributed testing guide).
Related tools and topics
Section titled “Related tools and topics”| Resource | Use when |
|---|---|
| OutOfMemoryError heap | Java heap space exhaustion |
| Metaspace & GC overhead | ClassLoader and Metaspace memory leaks |
| Thread Calculator | Calculate required thread count from throughput targets |
| Heap Estimator | Sizing JVM heap and native memory |
| Distributed testing | Setting up multi-node remote load generators |
Frequently asked questions
Section titled “Frequently asked questions”Will increasing -Xmx (heap size) fix this error?
Section titled “Will increasing -Xmx (heap size) fix this error?”No. In fact, increasing -Xmx can make this error happen faster on machines with limited RAM, because the JVM heap reserves more physical memory, leaving less native unmanaged RAM for OS thread stacks.
How many threads can one JMeter instance safely run?
Section titled “How many threads can one JMeter instance safely run?”On modern 64-bit Linux servers with properly tuned ulimit and -Xss256k, a single CLI instance can typically run between 1,000 and 3,000 threads for standard HTTP APIs. Complex scripts with heavy Groovy processing or large payload buffers should stay under 1,000 threads per injector.