匿名內部類方式構建物件導致序列化失敗
問題描述:
以下程式碼為問題程式碼:
public class ItemDO implements Serializable {
private static final long serialVersionUID=-463144769925355007L;
...
private Map<String,String> langAndTitleMap;
...
}
public class ItemMultiLangDecorator implements ItemDecorator {
...
@Override
public ItemDO getItemDO() throws IcException {
...
if(titleMultiLangFieldMeta!=null){
itemDO.setLangAndTitleMap(new HashMap<String, String>(){{put(titleMultiLangFieldMeta.getFieldLang(),itemDO.getTitle());}});
}else{
itemDO.setLangAndTitleMap(new HashMap<String, String>(){{put(LanguageConstants.EN,itemDO.getTitle());}});
}
...
}
...
}
在應用釋出之後,日誌出現ItemDO類序列化報錯異常,如下:
java.io.NotSerializableException: com.taobao.item.manager.decorator.ItemMultiLangDecorator
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.taobao.item.util.CloneUtil.deepCloneBySerialize(CloneUtil.java:29)
at com.taobao.item.domain.ItemUpdateDO.mergeDbItem(ItemUpdateDO.java:320)
問題原因
雖然序列化的是ItemDO類,但是報錯卻是ItemMultiLangDecorator類,表面上看ItemDO裡面並無任何對ItemMultiLangDecorator引用,但是由於在構造HashMap例項時候採用了匿名內部類構造的方式,即{{ ... }}
形式,查閱資料得知道java會在匿名內部類的例項都持有一個外部封裝類例項的隱式引用,也就導致構建Map例項擁有所在外部類ItemMultiLangDecorator例項引用,而恰好外部類並沒有實現序列化介面。
本人也在本地寫了一個Demo再次重現該問題。
public class Inner implements Serializable{
private static final long serialVersionUID= -463144769925355007L;
private String name;
public void setName(String name) {
this.name = name;
}
}
public class Outer {
public Inner create(){
return new Inner(){
{
setName("Hello");
}
};
}
}
public class Main {
public static void main(String[] args) {
Inner inner=new Outer().create();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(inner);
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
執行後會丟擲Outer類序列化錯誤,在IDE中斷點,可以看到Inner類持有外部類例項引用,如圖:
相關文章
- 匿名內部類
- Java之區域性匿名內部類物件Java物件
- 迴圈引用導致的json序列化失敗JSON
- Java內部類詳解--匿名內部類Java
- 匿名內部類理解
- 物件導向之內部類物件
- Drone構建失敗,一次drone依賴下載超時導致構建失敗的爬坑記錄
- Java類與匿名內部類Java
- java內部類,區域性內部類,靜態內部類,匿名內部類Java
- 匿名內部類的使用
- 匿名內部類方式實現執行緒的建立執行緒
- Docker 導致阿里雲 ECS 內網互通失敗Docker阿里內網
- 10-Java內部類——成員內部類、區域性內部類、匿名內部類Java
- java培訓教程:什麼是匿名內部類?怎樣建立匿名內部類?Java
- 內部類是什麼?匿名內部類又是什麼?
- dotnet 9 WPF 專案禁用 IncludePackageReferencesDuringMarkupCompilation 導致原始碼包 XAML 構建失敗Package原始碼
- Java中的匿名內部類及內部類的二三事Java
- dotnet 記龍芯麒麟教育版安全中心攔截檔案 導致 docker 內 CI CD 構建失敗Docker
- java匿名內部類:“ 儂好,世界”Java
- JAVA物件導向基礎--N種內部類Java物件
- Day 14 匿名函式 內建函式 物件導向程式設計函式物件程式設計
- 匿名內部類中關於new Runnable ( )
- 記 Kylin 麒麟系統安全中心攔截導致 dotnet sdk 找不到 OpenSsl 構建失敗
- Java_介面回撥與匿名內部類Java
- 小程式構建 npm 失敗NPM
- springboot衝突導致的發版失敗Spring Boot
- 關於java匿名內部類初始化法Java
- 用匿名內部類實現 Java 同步回撥Java
- 故障分析 | DDL 導致的 Xtrabackup 備份失敗
- scala_繼承、型別判斷、抽象類、匿名內部類繼承型別抽象
- sock鎖檔案導致的MySQL啟動失敗MySql
- 記一次Docker構建失敗Docker
- shiro org.apache.shiro.session.mgt.SimpleSession物件 反序列化失敗ApacheSession物件
- rman備份的時候讀取v$session_longops失敗導致備份失敗SessionGo
- 物件導向--內部屬性型別物件型別
- lambda表示式在oj中會比匿名內部類慢
- MongoDB例項重啟失敗探究(大事務Redo導致)MongoDB
- 企業使用ERP系統導致失敗的因素所在