• 解决


    一、认识问题:

    首先我们通过下面这个 测试程序 来认识这个问题: 运行的环境 (有必要说明一下,不同环境会有不同的结果):32位 Windows XP,Sun JDK 1.6.0_18, eclipse 3.4, 测试程序:

    Java代码
    1. import java.util.concurrent.CountDownLatch;  
    2.   
    3. public class TestNativeOutOfMemoryError {  
    4.   
    5.     public static void main(String[] args) {  
    6.   
    7.         for (int i = 0;; i++) {  
    8.             System.out.println("i = " + i);  
    9.             new Thread(new HoldThread()).start();  
    10.         }  
    11.     }  
    12.   
    13. }  
    14.   
    15. class HoldThread extends Thread {  
    16.     CountDownLatch cdl = new CountDownLatch(1);  
    17.   
    18.     public HoldThread() {  
    19.         this.setDaemon(true);  
    20.     }  
    21.   
    22.     public void run() {  
    23.         try {  
    24.             cdl.await();  
    25.         } catch (InterruptedException e) {  
    26.         }  
    27.     }  
    28. }  
    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  减小单个线程的栈大小

  • 相关阅读:
    Android_NDK问题:APP_BUILD_SCRIPT points to an unknown file: <project_path>/jni/Android.mk
    Android开发问题集锦-Button初始为disable状态时自定义的selector不生效问题
    一步步学习Python-django开发-添加后台管理
    一步步学习Python-django开发-建立django数据库
    一步步学习Python-django开发-Mac下搭建Python-Django环境
    JAVA小知识点-Finally和Return的执行关系
    Android自定义组合控件内子控件无法显示问题
    《将博客搬至CSDN》
    idea自动生成try/catch代码块的快捷键
    转:Apache common包 CollectionUtils 使用详解
  • 原文地址:https://www.cnblogs.com/pdca/p/4795628.html
Copyright © 2020-2023  润新知