1. 序言
- 最近,在使用mvn test命令跑单元测试时,遇到了
java.lang.OutOfMemoryError: unable to create new native thread
错误 unable to create new thread
类型的OOM错误,一般都发生在应用程序无法创建新线程时候- 其出现的原因主要分为两种:
- 系统内存耗尽,无法为新线程分配内存
- 创建线程数超过了操作系统的限制(linux中可以通过
ulimit -a
查看系统的最大线程数)
- 这篇博客讲了很多排查上述错误的方法和实例: Troubleshoot OutOfMemoryError: Unable to Create New Native Thread
- 还有一篇中文翻译:解决OutOfMemoryError: unable to create new native thread问题
2. 具体的排查方法
- solution 1:通过堆栈信息,确定是否存在创建线程过多的问题
- 创建了多少线程?过度创建的线程的堆栈信息是什么?谁创建了这些线程?
- 一旦了解清楚,就能很快解决OOM的问题
- Solution 2:增加操作系统的线程数
- 通过
ulimit -a
查看操作系统的最大线程数,这里假设为1024 - 如果应用程序所需的线程数超过1024,可以通过增大操作系统的线程数解决问题
- 通过
- Solution 3:增加机器内存
- 如果发现操作系统的线程数并未达到上限,说明应用程序需要更多的内存来创建线程
- 此时,增加机器内存便可以解决问题
- Solution 4:减少JVM堆内存(
-Xmx
)- 增加机器内存涉及硬件操作,不是最佳的选择
- 这时,不要忘记:线程不是在JVM的堆内存中创建的!
- 如果为JVM分配堆内存后,剩余内存较少,也会导致
OOM: unable to create new native thread
- 在JDK 1.8中,需要减少
–Xmx
配置的值;在JDK 1.7中,需要减少堆内存和永久代内存(–Xmx
和-XX:MaxPermSize
)
- Solution 5: 减少进程数
- 减少进程数,与较少堆内存相似
- 如果Java进程数过多,即使每个进程使用的堆内存不大,但累积起来也会导致剩余内存较少,从而出现
OOM: unable to create new native thread
- Solution 6: 减少线程栈大小(
-Xss
)- 如果每个线程的堆栈较大,应用程序整体消耗的内存也会变大
- 可以根据实际情况,减少线程的堆栈大小,即通过
–Xss
设置线程堆栈为一个合理的、较小值 - 注意:
-Xss
不是设置得越小越好,过小的-Xss
值会导致应用程序出现java.lang.StackOverflowError
错误,甚至都无法启动JVM
3. 后记
- 博客Troubleshoot OutOfMemoryError: Unable to Create New Native Thread,还介绍了如何通过http://fastthread.io/进行dump文件分析
- 有空,可以阅读作者是如何借助http://fastthread.io/分析OOM原因的。甚至,可以亲自体验下http://fastthread.io/