常見OOM問題之無法創(chuàng)建新的本地線程問題詳解

本文來自于HeapDump性能社區(qū)! !有性能問題,上HeapDump性能社區(qū)!
正文:

Java 應用程序本質上是多線程的。這意味著用 Java 編寫的程序可以同時(表面上)做幾件事。例如——即使在只有一個處理器的機器上——當您將內容從一個窗口拖到另一個窗口時,在后臺播放的電影不會因為您一次執(zhí)行多項操作而停止。

考慮線程的一種方法是將它們視為可以向其提交任務以執(zhí)行的工人。如果您只有一名工人,他或她當時只能執(zhí)行一項任務。但是,當您擁有十幾個工人時,他們可以同時執(zhí)行您的多個命令。

現(xiàn)在,與物理世界中的工人一樣,JVM 中的線程需要一些肘部空間來執(zhí)行他們被召喚來處理的工作。當線程多于內存空間時,我們已經為問題奠定了基礎:

v2-6f8d4aaeebe7a371948b0325ebfbd1e7_1440w.png

消息java.lang.OutOfMemoryError: Unable to create new native thread意味著Java 應用程序已達到它可以啟動的線程數(shù)限制。

1,什么原因造成的?

您有機會遇到java.lang.OutOfMemoryError: Unable to create new native thread每當 JVM 向操作系統(tǒng)請求新線程時。每當?shù)讓硬僮飨到y(tǒng)無法分配新的本機線程時,就會拋出此 OutOfMemoryError。本機線程的確切限制非常依賴于平臺,因此我們建議通過運行類似于以下示例的測試來找出這些限制。但是,一般情況下,導致java.lang.OutOfMemoryError: Unable to create new native thread 的情況會經歷以下幾個階段:

  1. 運行在 JVM 中的應用程序請求一個新的 Java 線程
  2. JVM 本機代碼將創(chuàng)建新本機線程的請求代理到操作系統(tǒng)
  3. 操作系統(tǒng)嘗試創(chuàng)建一個新的本地線程,該線程需要為線程分配內存
  4. 操作系統(tǒng)將拒絕本機內存分配,因為 32 位 Java 進程大小已耗盡其內存地址空間 - 例如 (2-4) GB 進程大小限制已達到 - 或操作系統(tǒng)的虛擬內存已完全耗盡
  5. java.lang.OutOfMemoryError:無法創(chuàng)建新的本地線程引發(fā)錯誤。

2,舉個例子

以下示例在循環(huán)中創(chuàng)建并啟動新線程。運行代碼時,會快速達到操作系統(tǒng)限制并顯示java.lang.OutOfMemoryError: Unable to create new native thread消息。

while(true){
    new Thread(new Runnable(){
        public void run() {
            try {
                Thread.sleep(10000000);
            } catch(InterruptedException e) { }        
        }    
    }).start();
}

確切的本機線程限制取決于平臺,例如在 Windows、Linux 和 Mac OS X 上的測試表明:

  • 64 位 Mac OS X 10.9,Java 1.7.0_45 – JVM 在 #2031 線程創(chuàng)建后終止
  • 64 位 Ubuntu Linux,Java 1.7.0_45 – JVM 在 #31893 線程創(chuàng)建后終止
  • 64 位 Windows 7、Java 1.7.0_45 – 由于操作系統(tǒng)使用的線程模型不同,此錯誤似乎不會在此特定平臺上引發(fā)。在線程 #250,000 上,即使交換文件已增長到 10GB 并且應用程序面臨極端的性能問題,該進程仍處于活動狀態(tài)。

因此,請確保通過調用一個小測試了解自己的限制,并找出何時會觸發(fā)java.lang.OutOfMemoryError: Unable to create new native thread

3,解決方案

有時,您可以通過增加操作系統(tǒng)級別的限制來繞過無法創(chuàng)建新的本機線程問題。例如,如果您限制了 JVM 可以在用戶空間中產生的進程數(shù),您應該檢查并可能增加限制:

[root@dev ~]# ulimit -a
核心文件大?。▔K,-c)0
--- 為簡潔起見 ---
最大用戶進程 (-u) 1800

通常情況下,OutOfMemoryError 對新本地線程的限制表明存在編程錯誤。當您的應用程序產生數(shù)千個線程時,很可能出現(xiàn)了嚴重錯誤——沒有多少應用程序可以從如此大量的線程中受益。

解決問題的一種方法是開始進行線程轉儲以了解情況。你通常會花幾天的時間來做這件事。我們的建議是將Plumbr連接到您的應用程序,以找出導致問題的原因以及如何在幾分鐘內解決它。

Java OOM系列專題:

第一篇:Java OOM 原理篇 : 什么是 Java OOM

第二篇:Java OOM 基礎篇:常見的OutOfMemoryError 場景一:Java heap space 堆溢出問題詳解

第三篇:Java OOM 基礎篇:常見的OutOfMemoryError 場景二 : GC overhead limit exceeded 問題詳解

第四篇:Java OOM 基礎篇:常見的OutOfMemoryError 場景三: PermGen space 永久空間問題詳解

第五篇:Java OOM 基礎篇:常見的OutOfMemoryError 場景四: Permgen size 元空間問題詳解

第六篇:Java OOM 實戰(zhàn)篇:應用故障之Java heap space 堆溢出實戰(zhàn)

第七篇:Java OOM 高級篇:體驗了一把線上CPU100%及應用OOM的排查和解決過程

第八篇:Java OOM 高級篇:線上Docker 上Springboot程序OOM問題的排查分享

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容