此次应用出现OOM异常分析如下
1. 现象:
Caused by: java.lang.OutOfMemoryError:unable to create new native thread
atjava.lang.Thread.start0(Native Method)
atjava.lang.Thread.start(Thread.java:714)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:949)
atjava.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)
2. 现象解释:
无法创建本地线程
3. tomcat的jvm配置
JAVA_OPTS="-server –Xms1024m –Xmx1024m-XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=256m"
4. 参数解释
-Xms JVM堆初始化值
-Xmx JVM堆最大值
-XX:PermSize JVM方法区(永久代)值
-XX:MaxPermSize JVM方法区(永久代)最大值
-XX:MaxNewSize JVM堆区新生代最大值
-Xss 每个线程栈的大小,默认1M
5. 主机应用情况
主机上部署5个tomcat应用,主机内存8G
6. 分析情况
根据OOM异常信息:无法创建新的本地线程得知是本地线程无法满足现有应用的使用。线程的内存分配属于栈区,栈区的大小是动态变化的,是系统内存在分配完给jvm及自己系统保留运行内存后的剩余的可用大小。由于我们设置的–Xms1024m,所以5个tomcat应用所占的内存值为5G,保守估计系统保留500M运行内存,此时内存值剩余8-5.5=2.5G.所以目前只剩余2.5g内存供创建线程使用,根据-Xss默认为1M的线程栈大小得出可创建2500多个线程。均分到5个应用中,每个应用可创建的平均线程数为500个。
在生产上命令ps hH p <pid> | wc -l查看了正常运行下的应用的进程的线程数为375个。正常情况下线程数为平均值的75%。所以在偶发高峰期是很有可能达到极限的值。
7. 解决方法
既然可创建的线程数不是很够,那就加大可创建的线程数。
从分析中得知可创建的线程数的影响因子有三个:系统的内存、tomcat应用的内存-Xms及-Xmx、线程大小-Xss。得出四个方案可选。
一、 将tomcat应用的-Xms1024堆区初始大小减小,比如减为-Xms 512,这时tomcat启动占的总内存为2.5g,从而节省出2.5g给线程使用,线程多出2500个。但是随着程序的运行和访问量加大,tomcat堆区的占用内存会向-Xmx1024靠拢,当都达到最大值1024,这时同样会出现只剩2.5g给创建本地线程使用。所以这时需要看应用的gc情况得出使用堆区的大小以估算未来一个使用情况,再考虑此种方案。
二、 将线程大小-Xss默认值1M减小改为设定值512kb。这样线程数从以前的2500个加倍到5000个。考虑目前系统的方法不是很复杂,每个线程给512kb的大小还是足够的,所以此种方法比较好。
三、 将系统内存加大,比如加个4g,线程数就可增加4000多个。这种方法最好,但是要钱去买内存。
四、 把5个应用部署到2台或者3台主机上,这样就不仅是线程数增加,程序的处理能力也加强,当然这更费钱。
---------------------
原文:https://blog.csdn.net/penghaiping1001/article/details/73199300