
測試環(huán)境應(yīng)用部署突然報錯 unable to create new native thread
排查方向:
1、機器內(nèi)存是否足夠為新線程分配內(nèi)存
2、創(chuàng)建線程數(shù)是否超過了操作系統(tǒng)的限制
線程在堆內(nèi)存之外的內(nèi)存上創(chuàng)建,所以如果分配了堆內(nèi)存之后只剩下很少的可用內(nèi)存,依然可能遇到j(luò)ava.lang.OutOfMemoryError: unable to create new native thread。
考慮如下場景:系統(tǒng)總內(nèi)存6G,堆內(nèi)存分配了5G,元空間512M。在這種情況下,JVM占用了5.5G內(nèi)存,系統(tǒng)進程、其他用戶進程和線程將共用剩下的0.5G內(nèi)存,很有可能沒有足夠的可用內(nèi)存創(chuàng)建新的線程。如果是這種情況,可考慮減小堆內(nèi)存。
-Xss: 設(shè)置每個線程的棧容量。例如,-Xss128k 設(shè)置每個線程的棧大小為128KB。
如果設(shè)置的偏大,創(chuàng)建的線程較多,JVM創(chuàng)建新的線程無法申請足夠內(nèi)存,則會拋出OutOfMemoryError異常。
同時,如果設(shè)置太小,線程在運行過程中,線程的調(diào)用棧深度增加,JVM可能會拋出StackOverflowError。
排查過程:
1、通過free命令查看內(nèi)存使用情況
2、通過ps -ef|grep java查看機器上運行的jvm示例,以及jvm啟動參數(shù)
3、通過jstack 工具來確定Java應(yīng)用創(chuàng)建了多少線程
jstack 輸出會列出所有的線程信息。每個線程信息以 "線程名稱" os_prio=優(yōu)先級 tid=線程ID nid=本地線程ID 的形式開始。你可以通過計數(shù)這些行的數(shù)量來確定當前活動的線程總數(shù)。
如果想自動化這個過程,可以使用腳本來解析 jstack 的輸出,并統(tǒng)計線程數(shù)量。例如,可以使用以下命令來統(tǒng)計:
ps -ef | grep java 在輸出結(jié)果中找到你的應(yīng)用程序?qū)?yīng)的進程ID。
jstack {進程id如12345} | grep -c '^"' 這個命令會統(tǒng)計以雙引號開頭的行數(shù),即線程的數(shù)量。
4、調(diào)整操作系統(tǒng)線程數(shù)閾值
操作系統(tǒng)會限制進程允許創(chuàng)建的線程數(shù),使用ulimit -u命令查看限制。某些服務(wù)器上此閾值設(shè)置的過小,比如1024。一旦應(yīng)用創(chuàng)建超過1024個線程,就會遇到j(luò)ava.lang.OutOfMemoryError: unable to create new native thread問題。如果是這種情況,可以調(diào)大操作系統(tǒng)線程數(shù)閾值。