<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          fastjson的這些坑,你誤入了沒?

          共 2668字,需瀏覽 6分鐘

           ·

          2020-07-28 15:59

          背景:最近 fastjson 被爆出新的遠(yuǎn)程代碼執(zhí)行漏洞之后,趕緊督促項(xiàng)目組快馬加鞭去修改(吐槽:真改不動(dòng),架不住項(xiàng)目既多又老),鑒于項(xiàng)目不同,依賴的 fastjson 版本也不同,本次著重談 fastjson 1.2.16 版本遇到的那些問題?1

          1

          兼容性:低版本沒問題,高版本拋異常?

          一、拋問題。

          摘取部分代碼片段,稍加改造如下。
          import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;
          import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;
          /** * fastjson 坑??! * * @author 一猿小講 */public class T { public static void main(String[] args) { JSONObject retJson = new JSONObject(); retJson.put("retCode", "0000"); retJson.put("retMsg", "Pay Succ");
          List> retList = new ArrayList>(); Map retMap = new HashMap(); retMap.put("orderId", "O010000088888"); retMap.put("payerName", "張三"); retList.add(retMap);
          retJson.put("retList", retList);
          if (retJson.containsKey("retList")) { JSONArray jsonArray = retJson.getJSONArray("retList"); for (Object object : jsonArray) { JSONObject orderObject = (JSONObject) object; System.out.println("假裝要執(zhí)行的處理===>" + orderObject); } } }}
          引入依賴(低版本):
              com.alibaba    fastjson    1.2.16
          代碼跑起來(真爽,飛一般的感覺):
          假裝要執(zhí)行的處理===>{"orderId":"O010000088888","payerName":"張三"}
          此時(shí),把 fastjson 升級(jí)成高版本:
              com.alibaba    fastjson    1.2.70
          代碼跑起來(浪奔浪流,萬里濤濤淚水永不休):
          Exception in thread "main" java.lang.ClassCastException: java.util.HashMap cannot be cast to com.alibaba.fastjson.JSONObject  at T.main(T.java:31)
          很明顯,第 31?行代碼拋出了異常
          JSONObject orderObject = (JSONObject) object;
          而且很明確:java.util.HashMap不能轉(zhuǎn)換成com.alibaba.fastjson.JSONObject。

          二、1.2.16 版本沒問題,升級(jí)到 1.2.70 就拋異常,敢問這是為什么?

          分析一:fastjson 1.2.16 版本下捉蟲子。


          分析二:fastjson 1.2.70?版本下捉蟲子。


          版本 1.2.16 vs?版本 1.2.70:
          • 兩幅圖的標(biāo)注?1 對(duì)比著看,會(huì)發(fā)現(xiàn)低版本的 JSONArray 中存進(jìn)去的是 JSONObject,而高版本的存進(jìn)去的是 HashMap;

          • 兩幅圖的標(biāo)注 2 對(duì)比著看,會(huì)發(fā)現(xiàn)低版本中 JSONObject 強(qiáng)轉(zhuǎn)成 JSONObject,當(dāng)然沒問題,而高版本拿 HashMap 強(qiáng)轉(zhuǎn)成 JSONObject 就會(huì)出現(xiàn) ClassCastException。


          到這兒,感覺還不是很解氣,勢(shì)必要打破砂鍋刨到底!

          版本 1.2.16 的源碼刨到底:

          而順著版本 1.2.16 的源碼一路看到底,會(huì)發(fā)現(xiàn)會(huì)對(duì) Map 進(jìn)行二次封裝處理,最終會(huì)包裝成 JSONObject 對(duì)象(這或許就是能強(qiáng)轉(zhuǎn)成 JSONObject 的原因,存進(jìn)去的是牛,強(qiáng)轉(zhuǎn)成牛,當(dāng)然沒問題)。


          版本 1.2.70?的源碼刨到底:

          版本 1.2.70 vs 版本 1.2.16,很顯然 1.2.70?版本增加了一個(gè)集合的條件分支判斷,如果根據(jù) key 獲取的 value 是 List,則會(huì)構(gòu)建 JSONArray 對(duì)象,如下面源碼截圖示意,List 里面的值不會(huì)做變化,如果 List 中放入的是 Map,則不會(huì)對(duì) Map 進(jìn)行二次處理(這可能就是強(qiáng)制轉(zhuǎn)換成 JSONObect 失敗的原因,存進(jìn)去的是牛,非要強(qiáng)轉(zhuǎn)成馬,當(dāng)然行不通)。


          三、該怎么解決版本升級(jí),帶來的兼容性問題呢?


          很簡(jiǎn)單,既然高版本的沒有對(duì) list 中的 Object 進(jìn)行轉(zhuǎn)換,咱們就刻意調(diào)用 toJSON 方法進(jìn)行轉(zhuǎn)換一番。

          retJson.put("retList", retList);修改為retJson.put("retList", JSON.toJSON(retList));

          代碼跑起來,Debug 看看效果如何:

          很明顯,JSONArray 中獲取的 object 類型已變?yōu)?JSONObject,當(dāng)然在 1.2.16、1.2.70 版本跑起來都暢通無阻,那么版本升級(jí)帶來的問題就迎刃而解。

          四、閑扯淡(走心)

          • 寫代碼時(shí)候還是需要注意點(diǎn),能稍微規(guī)范些,就盡量按照規(guī)范,就如本次提到的問題,向 JSONObject 中加入 List 時(shí),不妨先提前 toJSON 轉(zhuǎn)換一番,這樣版本升級(jí)也不會(huì)有問題。


          • 由于依賴包升級(jí)導(dǎo)致不兼容的情況很常見,不過絕大多數(shù)都是向下兼容的,例如 JDK ... 5、6、7、8 ...,所以如果你正在開發(fā)核心代碼,若涉及到版本更新,盡量考慮兼容性問題,如果涉及到老功能廢棄時(shí),不妨采用注解標(biāo)注一下,這樣后人會(huì)盡早發(fā)現(xiàn)問題。

          2

          ?不規(guī)范的傳入:導(dǎo)致內(nèi)存溢出??

          分享一段有意思的代碼,一起享受其中樂趣。

          import?com.alibaba.fastjson.JSON;/**?* fastjson 坑?。?/span> * @author 一猿小講 */public class T {    public static void main(String[] args) {        String str = "{\"key1\":\"\\value1\"}";        Object obj = JSON.parse(str);        System.out.println(obj);    }}

          代碼能跑起來,運(yùn)行結(jié)果絕對(duì)正常

          {"key1":"\u000Balue1"}

          此時(shí),我們動(dòng)點(diǎn)手腳,把 value1 的值變掉

          String str = "{\"key1\":\"\\x";

          程序運(yùn)行,word 天,驚呆!

          Exception in thread "main" java.lang.OutOfMemoryError: Java heap space  at com.alibaba.fastjson.parser.JSONLexerBase.putChar(JSONLexerBase.java:2835)  at com.alibaba.fastjson.parser.JSONLexerBase.scanString(JSONLexerBase.java:866)  at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:428)  at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1302)  at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1268)  at com.alibaba.fastjson.JSON.parse(JSON.java:137)  at com.alibaba.fastjson.JSON.parse(JSON.java:128)  at T.main(T.java:11)

          好奇不?咋回事?Debug 分析一番就清楚啦。

          當(dāng) json 字符串是以?\x 結(jié)尾時(shí),由于低版本的 fastjson 并未對(duì)其進(jìn)行校驗(yàn),將會(huì)導(dǎo)致其繼續(xù)嘗試獲取字符。

          由于 index>= this.len 始終成立,則意味著會(huì)直接獲取到?\u001A,相當(dāng)于 26,帶來的結(jié)果就是 isEOF 永遠(yuǎn)為 false,意味著要無休止的讀下去。

          就這樣陷入了死循環(huán) 1-->2-->3-->1,直到內(nèi)存溢出。

          Debug 一趟肯定比我說的要清楚,當(dāng)然,此問題早已在版本 1.2.60 中修復(fù)。

          1.2.70?版本肯定也不會(huì)有此問題啦,在高版本下直接提示格式錯(cuò)誤啦,擺脫了內(nèi)存異常。

          Exception in thread "main" com.alibaba.fastjson.JSONException: invalid escape character \x  at com.alibaba.fastjson.parser.JSONLexerBase.scanString(JSONLexerBase.java:984)  at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:479)  at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1401)  at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1367)  at com.alibaba.fastjson.JSON.parse(JSON.java:183)  at com.alibaba.fastjson.JSON.parse(JSON.java:193)  at com.alibaba.fastjson.JSON.parse(JSON.java:149)  at T.main(T.java:11)

          走心:

          • 金無足赤人無完人,代碼有 Bug 很正常,需要一步一步去迭代,要敢于讓團(tuán)隊(duì)犯錯(cuò)、試錯(cuò)、容錯(cuò)。

          • 通過此段測(cè)試,項(xiàng)目開發(fā)中參數(shù)格式校驗(yàn)就很有必要。

          3

          寄語寫最后

          本次,僅以項(xiàng)目中依賴 fastjson 類庫作為切入點(diǎn),主要想傳達(dá):在使用三方輪子時(shí),盡可能做對(duì)三方的輪子了如之掌,知己知彼方能百戰(zhàn)不殆。

          另外,借助 fastjson 升級(jí)的事情,也想傳達(dá)寫出規(guī)范性的代碼,是很有必要,不然升級(jí)的時(shí)候就很麻煩。

          文末送書

          ps:今天開始后面會(huì)有一個(gè)長(zhǎng)期送書計(jì)劃,會(huì)把廣告恰飯的一部分收入回饋給粉絲。


          參與形式也都不一樣,本期送書關(guān)鍵字為:0724123456


          在后臺(tái)回復(fù)即可以抽獎(jiǎng)了。如圖所示

          挑選了3本書籍,中獎(jiǎng)?wù)呖呻S意指定其中一本。

          事實(shí)證明:參與抽獎(jiǎng)和中獎(jiǎng)的每次也都是一小部分人


          推薦閱讀:

          聽說你的JWT庫用起來特別扭,推薦這款賊好用的!
          如何實(shí)時(shí)主動(dòng)監(jiān)控你的網(wǎng)站接口是否掛掉并及時(shí)報(bào)警
          InnoDB索引允許NULL對(duì)性能有影響嗎

          瀏覽 47
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产在线观看999 | 亚洲无砖无码 | 国产精品44 | 亚洲字幕在线观看视频 | 黄色毛片在线 |