踩坑了,JDK8中HashMap依然會死循環!

 

 是否你聽說過JDK8之後HashMap已經解決的擴容死循環的問題,雖然HashMap依然說執行緒不安全,但是不會造成伺服器load飆升的問題。

 

然而事實並非如此。少年可曾了解一種紅黑樹成環的場景,=v=

 

今日在查看監控時候發現,某一台機器load飆升

 

 

 

 

感覺問題不對勁,ssh大法登陸機器,top,top -Hp,jstack,jmap四連擊保存下來堆棧,cpu使用最高的執行緒,記憶體資訊準備分析。

 

首先查看使用最耗費cpu的執行緒堆棧資訊

cat stack | grep -i 34670 -C10 --color

 

 

 

我勒個去,HashMap,猜測八成死循環了,但是我們使用的JDK8,在8中通過棧封閉的鏈表替換,解決了擴容死循環的問題。疑惑,繼續往下看。

 

根據堆棧資訊,root方法是問題所在,點開HashMap源碼

 

 

 

好嘛,load飆高,程式碼有個for語句,我覺得鐵定死循環了,看程式碼情況只可能是兩個紅黑樹節點的父親節點相互引用才可以導致無法走出這個for語句。

 

然而這都是我的猜測,我沒有證據。而且讓我追紅黑樹的程式碼,也是需要耗費大量時間的事情,我需要快速驗證我的猜測。

 

我之前dump下來了堆記憶體資訊,我通過jhat 命令生成html的記憶體資訊頁面

 

 

然後輸入//localhost:7000查看

我先找業務程式碼中持有這個HashMap的對象,然後點進去查詢內部資訊

 

 

因為數據都放在table中,點擊Table欄位,查看其內容

 

 

table中存在唯一的一個TreeNode節點,這肯定是已經變成了紅黑樹了

點進去查看

 

 

點擊parent欄位資訊

 

 

0x72745d828與0x72745d7b8兩個TreeNode節點的Parent引用都是對方。

後續打算深入研究一下紅黑樹什麼場景會造成這個原因。

最後,無論什麼並發場景請別使用HashMap,ConcurrentHashmap大法好