[已解決]報異常java.io.InvalidClassException的解決方法|對象序列化實現Serializable會出現java.io.InvalidClassException的異常

一、前言

今天在增加完新功能後, 部署的時候,突然就遇到了java.io.InvalidClassException的問題,這些都是我們平常不注意細節造成的後果。

具體異常如下

 

分析異常:Caused by:java. io. InvalidClassException: com. eastcom xxx.xxxxxx. bean. AlarmReq; local class incompatible: stream classdesc serialversionUID =1631280650588763177, local class seriaiversionuId = 6638111461888145730

 

二、分析原因

首先我們的系統架構,是因爲要將對象通過

AlarmReq alarmReq= JSONObject.toJavaObject(json,AlarmReq.class);
redisQueue = redisTaskContainer.getRedisQueue();
redisQueue.pushFromHead(alarmReq);

上述方法會將對象序列化到redis內存中,然後又再通過 redisTemplate.getValueSerializer().deserialize() 方法將數據反序列化到bean對象,這樣的話,如果改動了這個bean對象的話,即加了屬性的話,就會導致serialVersionUID會變,而且當時我們的bean對象即上述的AlarmReq對象,當時是沒有加serialVersionUID的。

由於序列化時該類的serialVersionUID是JVM根據類名及其屬性的哈希值生成的。當類的屬性有變動時,serialVersionUID也會相應變動,從而導致redis中的老數據反序列化爲AlarmReq bean對象時,serialVersionUID匹配不上而失敗,會報出java. io. InvalidClassException。

 

三、解決問題

知道原因了,我們就可以解決問題了

方法1:不考慮和老數據兼容的話,直接在你實現了Serializable的這個對象加一段serialVersionUID代碼,如果還報InvalidClassException,將redis上的老數據清除

private static final long serialVersionUID = 1L;

方法2:兼容老數據,找到老數據的serialVersionUID,就是上述報錯的地方,會將老數據的serialVersionUID報出來,比如我這裏的老數據的就是1631280650588763177 這一串,你只要加 UID=1631280650588763177 這個就可以了。

private static final long serialVersionUID = 1631280650588763177L;

 

四、總結

可能好多人在寫對象以及序列化對象的時候,是沒有加private static final long serialVersionUID的,但是也沒有見到有報InvalidClassException異常的,那是因爲你部署的單體系統架構,實時序列化和反序列化的,每次系統重啓就又重新實例對象,所以即使改變了對象增加屬性,也不會出現老對象和新對象serialVersionUID 不一致的情況,所以也就不會出現java. io. InvalidClassException。

所以以後你們寫對象並且要序列化的話,一定要隨手加上serialVersionUID這段代碼。

如果你們去看源碼,HashMap、ArrayList 等這些神級代碼的時候,你們可以看到,他們都是加了 serialVersionUID 代碼的

 

 

五、使用idea工具自動生成

1、按照下圖所示,設置好後,不要忘記點擊【Apply】應用一下

 

2、在實現了 Serializable的bean類下, 鼠標移到bean類名處,按住 alt+enter,就會自動彈出【Add serialVersionUID field】

選中即可自動生成啦,


 

參考文章:

https://blog.csdn.net/z3278221/article/details/90298812

感謝原作者的分享,讓技術人能夠更快的解決問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章