Java基础、中级、高级、架构面试资料

java.lang.OutOfMemoryError: Unable to create new native thread

JAVA herman 12645浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

没有一样东西是可以随便挥霍的,亲情、爱情都不行。JVM 也不行!

程序也都是和现实世界规律一致的。Java 中存在多线程,支持同时执行多项任务。所以物理机上即使只有一个CPU,我们也可以同时运行多个程序。

JVM 中的线程也需要内存空间来执行自己的任务。如果线程数量太多就会把相应的内存空间给消耗完,引出新的问题!

Unable to create new native thread

JVM 向操作系统申请创建新的 native thread(原生线程)时,就有可能会碰到 java.lang.OutOfMemoryError: Unable to create new native thread 错误。如果底层操作系统创建新的 native thread 失败,JVM 就会抛出相应的 OutOfMemoryError。

java.lang.OutOfMemoryError: Unable to create new native thread 错误的场景大多是这样产生的:

  • Java 程序向 JVM 请求创建一个新的Java线程;
  • JVM 本地代码(native code)代理该请求,尝试创建一个操作系统级别的 native thread(原生线程);
  • 操作系统尝试创建一个新的 native thread,需要同时分配一些内存给该线程;
  • 如果操作系统的虚拟内存已耗尽,或者是受到 32 位进程的地址空间限制(约2-4GB),OS就会拒绝本地内存分配;
  • 然后 JVM 就会抛出 java.lang.OutOfMemoryError: Unable to create new native thread 错误。

所以说产生 java.lang.OutOfMemoryError: Unable to create new native thread 错误的具体原因就是:程序创建的线程数量已达到上限值。

下面我们来一段代码,自己利用程序产生一个 java.lang.OutOfMemoryError: Unable to create new native thread 错误。

while(true){
    new Thread(new Runnable(){
        public void run() {
            try {
                Thread.sleep(10000000);
            } catch(InterruptedException e) { }        
        } // 业余草:www.xttblog.com
    }).start();
} 

利用死循环创建 N 多个新线程。相信用不了多久,就会产生 java.lang.OutOfMemoryError: Unable to create new native thread 错误。

原生线程的数量由具体环境决定。如果你想测试出不同系统的极限在哪里就可以使用上面的示例代码在不同的操作系统上进行测试!

有时候我们通过可以修改系统限制来避开 Unable to create new native thread 问题。

ulimit -a 

ulimit -a

似乎是 max user processes 数不足?那我们将它放大一倍试一试!

ulimit -u 2048

但是根据我的经验来说,产生 java.lang.OutOfMemoryError: Unable to create new native thread 问题,大多都是因为你的程序有问题。你的程序可能创建了成千上万的线程,但是没有几个程序可以 Hold 住上万个线程的。

那么该怎么排查这类问题呢?

可以通过 jstack 确定应用创建了多少线程?超量创建的线程的堆栈信息是怎样的?谁创建了这些线程?一旦明确了这些问题,便很容易解决。

关于 jstack 使用的案例,可以参考我的这篇文章《详解使用 jstack 跟踪 java 异常代码》。这篇文章中的图片,由于交不起钱,七牛云中的外链都失效了,大家凑合着看吧!

其实我们有一个公式,可以大致的计算出程序能创建的线程数。这个公式如下:

(MaxProcessMemory – JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads 

这 4 个内存相关的参数,我解释一下:

  • MaxProcessMemory:指的是一个进程的最大内存
  • JVMMemory:JVM内存
  • ReservedOsMemory:保留的操作系统内存
  • ThreadStackSize:线程栈的大小

根据这个公式,我们能大致的判断出是不是系统参数设置的问题!

参考资料

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » java.lang.OutOfMemoryError: Unable to create new native thread