點擊上方“ 搜雲庫技術團隊 ”關注,選擇“ 設爲星標

回覆“ 1024 ”或 面試題 獲取 4T架構師 資料

Json-lib 介紹

Json-lib 是以前 Java 常用的一個 Json 庫,最後的版本是 2.4,分別提供了 JDK 1.3 和 1.5 的支持,最後更新時間是 2010年12月14日。雖然已經很多年不維護了,但在搜索引擎上搜索 "Java Json" 等相關的關鍵詞發現好像一直還有人在介紹和使用這個庫。

項目官網是

http://json-lib.sourceforge.net

一句話結論

Json-lib 在通過字符串解析每一個 Json 對象時,會對當前解析位置到字符串末尾進行 substring 操作,由於 JDK7 及以上的 substring 會完整拷貝截取後的內容,所以當遇到較大的 Json 數據並且含有較多對象時,會進行大量的字符數組複製操作,導致了大量的 CPU 和內存消耗,甚至嚴重的 Full GC 問題。

問題分析

某天發現線上生產服務器有不少 Full GC 問題,排查發現產生 Full GC 時某個老接口量會上漲,但這個接口除了解析 Json 外就是將解析後的數據存儲到了緩存中,遂懷疑跟接口請求參數大小有關,打日誌發現確實有比一般請求大得多的 Json 數據,但也只有 1MB 左右。爲了簡化這個問題,編寫如下的性能測試代碼。

上述代碼執行後平均每次解析需要 7秒左右才能完成,如下圖所示。

測試用的 Json 文件,“...” 處省略了 34,018 個相同內容,整個 Json 數據中包含了 3萬多個 Json 對象,實際測試的數據如下圖所示。

使用 Java Mission Control 記錄執行的情況,如下圖所示,可以看到分配了大量 char[] 數組。

翻看相關源碼,其中 JSONObject._fromJSONTokener 方法主要內容如下所示。可以看到其在代碼一開始就匹配是否爲 "null" 開頭。

而 matches 方法更是直接用 substring 截取當前位置到末尾的字符串,然後進行正則匹配。

字符串 substring 會傳入字符數組、起始位置和截取長度創建一個新的 String 對象。

在 JDK7 及以上,調用該構造方法時在最後一行會複製一遍截取後的數據,這也是導致整個問題的關鍵所在了。

來源:大魔王mAysWINd

www.cnblogs.com/mayswind/p/9222245.html

近期技術熱文

相關文章