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

工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题、分析问题、解决问题。 

一、认识问题: 

首先我们通过下面这个 测试程序 来认识这个问题:

运行的环境 (有必要说明一下,不同环境会有不同的结果):32位 Windows XP, 1.5.0_22, myeclipse 6.6,

测试程序: 

Java代码 

import java.util.concurrent.CountDownLatch;   

public class TestNativeOutOfMemoryError {   

    public static void main(String[] args) {   

        for (int i = 0;; i++) {   

            System.out.println("i = " + i);   

            new Thread(new HoldThread()).start();   

        }   

    }   

}   

 

class HoldThread extends Thread {   

    CountDownLatch cdl = new CountDownLatch(1);   

 

    public HoldThread() {   

        this.setDaemon(true);   

    }   

    public void run() {   

        try {   

            cdl.await();   

        } catch (InterruptedException e) {   

        }   

    }   

}  

import java.util.concurrent.CountDownLatch;

public class TestNativeOutOfMemoryError {

public static void main(String[] args) {

  for (int i = 0;; i++) {

   System.out.println("i = " + i);

   new Thread(new HoldThread()).start();

  }

}

}

class HoldThread extends Thread {

CountDownLatch cdl = new CountDownLatch(1);

public HoldThread() {

  this.setDaemon(true);

}

public void run() {

  try {

   cdl.await();

  } catch (InterruptedException e) {

  }

}

}  

 

不指定任何JVM参数,eclipse中直接运行输出,看到了这位朋友了吧:

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

    at java.lang.Thread.start0(Native Method)

    at java.lang.Thread.start(Thread.java:597)

    at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:20) 

 

二、分析问题: 

这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。能创建的线程数的具体计算公式如下: 

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

MaxProcessMemory 指的是一个进程的最大内存

JVMMemory         JVM内存

ReservedOsMemory  保留的操作系统内存

ThreadStackSize      线程栈的大小

在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。 

 

结合上面例子我们来对公式说明一下: 

MaxProcessMemory 在32位的 windows下是 2G

JVMMemory   eclipse默认启动的程序内存是64M

ReservedOsMemory  一般是150M左右

ThreadStackSize 32位 JDK 1.5默认的stacksize 256K左右

公式如下:

(2*1024*1024-64*1024-150*1024)/256 = 7336 

公式计算所得7336,和实践7117基本一致(有偏差是因为ReservedOsMemory不能很精确) 

由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。 

咦,有点背我们的常理,恩,让我们来验证一下,依旧使用上面的测试程序,加上下面的JVM参数,测试结果如下: 

ThreadStackSize      JVMMemory                    能创建的线程数

默认的256K             -Xms64m -Xmx64m    i = 7117

默认的256K             -Xms32m -Xmx32m    i = 7244

-Xss128k             -Xms64m -Xmx64m    i = ? 

完全和公式一致。 

三、解决问题: 

1, 如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。

2, 如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数:

a, MaxProcessMemory 使用64位操作系统

b, JVMMemory   减少JVMMemory的分配

c, ThreadStackSize  减小单个线程的栈大小

http://blog.csdn.net/kesay/article/details/5728810

 

目录
打赏
0
0
0
0
95
分享
相关文章
|
4月前
|
Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2024-11-26T20:55:26 of type java.time.format.Parsed
Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2024-11-26T20:55:26 of type java.time.format.Parsed
135 0
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
427 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
Exception in thread "main" java.lang.NoSuchMethodError: okhttp3.OkHttpClientBuilder.sslSocketFactory(Ljavax/net/ssl/SSLSocketFactory;Ljavax/net/ssl/X509TrustManager;)Lokhttp3/OkHttpClientBuilder; 问题处理
【10月更文挑战第26天】Exception in thread "main" java.lang.NoSuchMethodError: okhttp3.OkHttpClientBuilder.sslSocketFactory(Ljavax/net/ssl/SSLSocketFactory;Ljavax/net/ssl/X509TrustManager;)Lokhttp3/OkHttpClientBuilder; 问题处理
120 2
Java“Could Not Create Java Virtual Machine”解决
当在Java中遇到“Could Not Create Java Virtual Machine”错误时,通常是由于内存设置不当、Java版本不兼容、类路径错误或操作系统限制等原因导致JVM无法启动。解决方法包括调整内存参数、确认Java版本兼容性、检查类路径和启动参数、以及检查用户权限和文件系统。
1210 1
|
5月前
|
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
102 2
|
5月前
|
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
81 2
|
5月前
|
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
75 3
|
5月前
|
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
82 1
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
82 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等