• 线程ava.lang.OutOfMemoryError: unable to create new native thread


    近日开发遇到多线程的问题:

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


    Exception in thread "Thread-2" java.lang.OutOfMemoryError: unable to create new native thread


    原因是创建过多thread引出的问题,JVM此时无法再创建出更多的线程。这里的解释还是比较靠谱的 

    引用
    As you can see, the maximum number of threads I can create decreases as the heap size gets larger. This is because the JVM immediately reserves the address space specified for the maximum heap size - That's probably because it needs that memory to be contiguous

    表象便是当JVM的heap size设置过大时,thread的创建数量便会减少。这里找到了一个还算清晰的说明 

    引用
    Maximum heap size depends on maximum address space per process. 
    Maximum heap space is always smaller than maximum address space per process, because the process also needs space for stack, libraries, and so on.

    JVM的堆和进程所需的栈都会消耗进程地址空间(address space),而地址空间则取决于操作系统,Windows中 

    引用
    所有 32 位应用程序都有 4 GB 的进程地址空间(32 位地址最多可以映射 4 GB 的内存)。对于 Microsoft Windows 操作系统,应用程序可以访问 2 GB 的进程地址空间,称为用户模式虚拟地址空间。应用程序拥有的所有线程都共享同一个用户模式虚拟地址空间。其余 2 GB 为操作系统保留(也称为内核模式地址空间)。

    目前我的理解是,JVM申请的heap会占用相同大小的地址空间(address space)。在Windows 32位操作系统中,分配给每个程序的地址空间只有2GB(当然也有3GB的开关)。而每个不同的JVM的堆和其创建的进程栈都依赖于同一个进程地址空间,所以这也是此消彼长的原因。 

    有方法可以提高创建线程的数量: 
    1.减少JVM的heap size; 
    2.减少单个线程栈的大小,在JVM启动中使用-Xss参数。目前JDK1.4中每个线程栈所大小是256K,1.5是1M. 

    Map map=Thread.getAllStackTraces();
    System.out.println(map.size());
    把这两句话放在需要的方法里里,运行就可以得到结果了。
    下面这句话是java api的解释:
    Thread类。
    getAllStackTracespublic static Map<Thread,StackTraceElement[]> getAllStackTraces()返回所有活动线程的堆栈跟踪的一个映射。映射键是线程,而每个映射值都是一个 StackTraceElement 数组,该数组表示相应 Thread 的堆栈转储。返回的堆栈跟踪的格式都是针对 getStackTrace 方法指定的。 
    在调用该方法的同时,线程可能也在执行。每个线程的堆栈跟踪仅代表一个快照,并且每个堆栈跟踪都可以在不同时间获得。如果虚拟机没有线程的堆栈跟踪信息,则映射值中将返回一个零长度数组。 
    如果有安全管理器,则通过 RuntimePermission("getStackTrace") 权限和 RuntimePermission("modifyThreadGroup") 权限调用其 checkPermission 方法,查看是否可以获得所有线程的堆栈跟踪。


    假如你是需要监控java虚拟机线程运行状况的话,建议使用jdk自带的工具jvisualvm,有图形化的监控界面。 


  • 相关阅读:
    yum 安装pip
    sed和awk用法
    awk删除最后一个字符
    shell读取文件内容并进行变量赋值
    git 添加、提交、推送
    git 本地代码冲突解决,强制更新
    sys系统模块
    os模块
    time-时间模块
    环境变量的使用
  • 原文地址:https://www.cnblogs.com/wuyida/p/6300968.html
Copyright © 2020-2023  润新知