`
城的灯
  • 浏览: 150292 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JVM最大Thread数量

    博客分类:
  • 2013
阅读更多
原文地址:http://www.yangguo.info/2013/6/17/22.html

最近研发推送方案,需要大量线程来模拟手机客户端。在模拟手机客户端的时候,单个JVM线程数量始终卡在一万多一点,然后就报如下的错误:”java.lang.OutOfMemoryError: unable to create new native thread“。我在网上找了很多资料,都是分析32位的,都是准备模拟几千个或者几万个水平。因为我是使用64位的linux,并且要模拟50万,发现很多都不是很详细。对于这个OOM,根本无需多言,网上一堆关于JVM线程数的计算公式,此处我不妨再次引用一次:
(MaxProcessMemory - JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads 。MaxProcessMemory:进程最大的寻址空间,关于不同系统的进程默认的最大寻址空间,可以参考如下表格:
Operating SystemMaximum Address Space Per Process
Redhat Linux 32 bit2 GB
Redhat Linux 64 bit3 GB
Windows 98/2000/NT/Me/XP2 GB
Solaris x86 (32 bit)4 GB
Solaris 32 bit4 GB
Solaris 64 bitTerabytes

JVMMemory: Heap + PermGen
ReservedOSMemory:Native heap,JNI
通过上面的说明大概就能估算出线程数量:
(MaxProcessMemory<固定值> – Xms<初始化值,最小值> – XX:PermSize<初始化值,最小值> – 100m<估算值>) / Xss = Number of threads<最大值>
公式已经放在上面了,这个时候各个值的设置地方如下:

Java虚拟机本身:
-Xms,-Xmx,-Xss

系统限制:
/proc/sys/kernel/pid_max
开始我也觉得奇怪,为什么需要修改pid呢?pid不是进程id嘛,我只是创建线程,并不创建进程,pid的大小跟我好像没有关系。查阅资料才发现,同一个进程的多个线程的pid其实是不同的。

/proc/sys/vm/max_map_count
max_map_count文件包含限制一个进程可以拥有的VMA(虚拟内存区域)的数量。虚拟内存区域是一个连续的虚拟地址空间区域。在进程的生命周期中,每当程序尝试在内存中映射文件,链接到共享内存段,或者分配堆空间的时候,这些区域将被创建。调优这个值将限制进程可拥有VMA的数量。限制一个进程拥有VMA的总数可能导致应用程序出错,因为当进程达到了VMA上线但又只能释放少量的内存给其他的内核进程使用时,操作系统会抛出内存不足的错误。如果你的操作系统在NORMAL区域仅占用少量的内存,那么调低这个值可以帮助释放内存给内核用。具体的可以查看redhat的这篇文章:http://www.redhat.com/magazine/001nov04/features/vm/,中文的话是这篇:http://www.oschina.net/translate/understanding-virtual-memory?print

还有注意ulimit -a中参数的大小
当然有人说下面这个两个需要修改,但是我测试下来,好像不用修改也行,反正我没有修改。
/proc/sys/kernel/thread-max
/etc/security/limits.d/90-nproc.conf

注意如果使用
#sysctl -w vm.max_map_count=200000
#sysctl -p
来修改,重启后值会改变,如果想永久改变需要如下操作:
vm.max_map_count=200000直接写到/etc/sysctl.conf中,然后执行sysctl -p

对于我的应用,此处还要设置一个socket端口的取值范围
net.ipv4.ip_local_port_range = 1024 65535
当然对于非socket应用是不需要设置该值的

至于上面各个参数的设置,可以去查看linux方面的一些资料。至于值到底多大,得根据你机器的性能来确定。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics