工作中碰着过这个题目好几次了,感觉有须要总结一下,所以有了这篇文章,这篇文章分为三个项目组:熟悉题目、解析题目、解决题目。
一、熟悉题目:
起首我们经由过程下面这个 测试法度 来熟悉这个题目: 运行的景象
(有须要申明一下,不合景象会有不合的成果):32位 Windows XP,Sun JDK 1.6.0_18, eclipse 3.4,
测试法度:
- 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中直接运行输出,看到了这位伴侣了吧:
i = 5602 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 一般是130M阁下
ThreadStackSize 32位 JDK 1.6默认的stacksize 325K阁下
公式如下:
(2*1024*1024-64*1024-130*1024)/325 = 5841
公式策画所得5841,和实践5602根蒂根基一致(有误差是因为ReservedOsMemory不克不及很正确)
由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越轻易产生java.lang.OutOfMemoryError: unable to create new native thread。
咦,有点背我们的常理,恩,让我们来验证一下,依旧应用上方的测试法度,加高低面的JVM参数,测试成果如下: ThreadStackSize JVMMemory 能创建的线程数
默认的325K -Xms1024m -Xmx1024m i = 2655
默认的325K -Xms1224m -Xmx1224m i = 2072
默认的325K -Xms1324m -Xmx1324m i = 1753
默认的325K -Xms1424m -Xmx1424m i = 1435
-Xss1024k -Xms1424m -Xmx1424m i = 452 完全和公式一致。
三、解决题目: 1, 若是法度中有bug,导致创建多量不须要的线程或者线程没有及时收受接管,那么必须解决这个bug,批改参数是不克不及解决题目的。
2, 若是法度确切须要多量的线程,现有的设置不克不及达到请求,那么可以经由过程批改MaxProcessMemory,JVMMemory,ThreadStackSize这三个身分,来增长能创建的线程数:
a, MaxProcessMemory 应用64位操纵体系
b, JVMMemory 削减JVMMemory的分派
c, ThreadStackSize 减小单个线程的栈大小
|