Why This Happens
Each Java thread maps to a native OS thread, and each thread consumes stack memory. When you create thousands of threads, the OS runs out of memory for thread stacks or hits the process thread limit. Use thread pools instead of creating unbounded threads.
The Problem
for (int i = 0; i < 100_000; i++) {
new Thread(() -> {
try { Thread.sleep(60_000); } catch (Exception e) {}
}).start();
}The Fix
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 100_000; i++) {
executor.submit(() -> {
try { Thread.sleep(60_000); } catch (Exception e) {}
});
}
executor.shutdown();Step-by-Step Fix
- 1
Identify thread creation
Use jstack or a thread dump to see how many threads are alive and what they are doing.
- 2
Find unbounded thread creation
Search for new Thread() or Executors.newCachedThreadPool() that could create unlimited threads.
- 3
Use a bounded thread pool
Replace direct thread creation with a fixed-size ExecutorService, or reduce stack size with -Xss if threads are using more stack than needed.
Bugsly catches this automatically
Bugsly's AI analyzes this error pattern in real-time, explains what went wrong in plain English, and suggests the exact fix — before your users even report it.
Try Bugsly free