jvm最大线程数
摘自:http://sesame.iteye.com/blog/622670
工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题、分析问题、解决问题。
一、认识问题:
首先我们通过下面这个 测试程序 来认识这个问题:
运行的环境 (有必要说明一下,不同环境会有不同的结果):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 = ;; i++) {
- System.out.println("i = " + i);
- new Thread(new HoldThread()).start();
- }
- }
- }
- class HoldThread extends Thread {
- CountDownLatch cdl = new CountDownLatch();
- 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中直接运行输出,看到了这位朋友了吧:
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 减小单个线程的栈大小
四、其他:
在java应用中,有时候会出现这样的错误:OutOfMemoryError: unable
to create new native
thread.这种怪事是因为JVM已经被系统分配了大量的内存(比如1.5G),并且它至少要占用可用内存的一半。有人发现,在线程个数很多的情况下,你分配给JVM的内存越多,那么,上述错误发生的可能性就越大。
每一个32位的进程最多可以使用2G的可用内存,因为另外2G被操作系统保留。这里假设使用1.5G给JVM,那么还余下500M可用内存。这500M内存中的一部分必须用于系统dll的加载,那么真正剩下的也许只有400M,现在关键的地方出现了:当你使用Java创建一个线程,在JVM的内存里也会创建一个Thread对象,但是同时也会在操作系统里创建一个真正的物理线程(参考JVM规范),操作系统会在余下的400兆内存里创建这个物理线程,而不是在JVM的1500M的内存堆里创建。在jdk1.4里头,默认的栈大小是256KB,但是在jdk1.5里头,默认的栈大小为1M每线程,因此,在余下400M的可用内存里边我们最多也只能创建400个可用线程。
这样结论就出来了,要想创建更多的线程,你必须减少分配给JVM的最大内存。还有一种做法是让JVM宿主在你的JNI代码里边。
给出一个有关能够创建线程的最大个数的估算公式:
(MaxProcessMemory
- JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of
threads
对于jdk1.5而言,假设操作系统保留120M内存:
1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB)
= ~380 threads
1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880
threads
对于栈大小为256KB的jdk1.4而言,
1.5GB allocated to JVM: ~1520
threads
1.0GB allocated to JVM: ~3520 threads
jvm最大线程数的更多相关文章
- Jvm支持的最大线程数
摘自 http://blog.csdn.net/xyls12345/article/details/26482387 JVM最大线程数 (2012-07-04 23:20:15) 转载▼ 标签: jv ...
- JVM可支持的最大线程数(转)
摘自:http://sesame.iteye.com/blog/622670 工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题.分析问题.解决问题. ...
- JVM可支持的最大线程数
转微博,因为他也是转载 不知道原出处 一.认识问题: 首先我们通过下面这个 测试程序 来认识这个问题:运行的环境 (有必要说明一下,不同环境会有不同的结果):32位 Windows XP,Sun J ...
- 180724-统计JVM进程中线程数两种方式小记
I. 统计进程中的线程数 相关系列博文推荐: 180711-JVM定位分析CPU性能消耗 180704-JDK常用监控参数 jvm调优的工具介绍 1. proc查询 /proc 目录以可读文本文件形式 ...
- 聊下并发和Tomcat线程数(错误更正)
本文前半部分结论存在严重错误,请看最后2015-1-20更新部分. 最近一直在解决线上一个问题,表现是: Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池 ...
- 聊下并发和Tomcat线程数(Updated)
最近一直在解决线上一个问题,表现是: Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看很多请求超过了1s. 服务器性能很好,Tomcat版本是 ...
- Java调优之jvm和线程的内存分析
本文来源于铁木箱子的博客http://www.mzone.cc 这几天因为自己开发的一个网站在768M内存的机器上撑不起100多个用户的运行,因为每个用户启用功能后,系统将为每个用户分配8个左右的独立 ...
- Tomcat设置最佳线程数总结
最佳线程数: 性能压测的情况下,起初随着用户数的增加,QPS会上升,当到了一定的阀值之后,用户数量增加QPS并不会增加,或者增加不明显,同时请求的响应时间却大幅增加.这个阀值我们认为是最佳线程数. 为 ...
- 浅谈并发和tomcat线程数
假设Tomcat每到固定一个时间会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看很多请求超过了1s. 服务器性能很好,Tomcat版本是7.0.54,配置如下 & ...
随机推荐
- MongoDB-6: MongoDB索引
一.简介 在MongoDB建立索引能提高查询效率,只需要扫描索引只存储的这个集合的一小部分,并只把这小部分加载到内存中,效率大大的提高,如果没有建立索引,在查询时,MongoDB必须执行全表扫描,在数 ...
- django-Query Ajax 实例 ($.ajax、$.post、$.get)
Jquery在异步提交方面封装的很好,直接用AJAX非常麻烦,Jquery大大简化了我们的操作,不用考虑浏览器的诧异了. 推荐一篇不错的jQuery Ajax 实例文章,忘记了可以去看看,地址为:ht ...
- make编译五
Make的运行 有时候,我们不想让我们的makefile 中的规则执行起来,我们只想检查一下我们的命令,或是执行的序列.于是我们可以使用make 命令的下述参数: “-n” “--just-print ...
- flask实现获取表单并执行shell
1.一个HTML form input和一个button提供给用户输入 2.使用flask的request获取用户输入的文件名 3.判断输入异常 4.执行shell命令touch aa.txt 并返回 ...
- Django CSRF cookie not set.错误
post提交表单报错: Forbidden (403) CSRF verification failed. Request aborted. You are seeing this message b ...
- GIL解释器,协程,gevent模块
GIL解释器锁 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CP ...
- delphi winio 输入
var key:byte;//ASCII码 btScancode:DWord; //键码begin key:=VkKeyScan('b'); btScancode:= MapVirtualKey(ke ...
- hadoop单击模式环境搭建
一 安装jdk 下载相应版本的jdk安装到相应目录,我的安装目录是/usr/lib/jdk1.8.0_40 下载完成后,在/etc/profile中设置一下环境变量,在文件最后追加如下内容 expor ...
- SVN插件下载地址及更新地址
SVN插件下载地址及更新地址,你根据需要选择你需要的版本.现在最新是1.8.xLinks for 1.8.x Release:Eclipse update site URL: http://subcl ...
- linux---(6/27)tr命令和sed命令详解
Tr命令: tr是简单的单个“字符”处理工具,而sed是功能非常强大的“字符串”处理工具. 用于查询,字符串2用于处理各种转换.tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始 ...
