匿名內部類方式構建物件導致序列化失敗
問題描述:
以下程式碼為問題程式碼:
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類持有外部類例項引用,如圖:
相關文章
- 源設定導致Docker映象構建失敗Docker
- 匿名內部類
- Java之區域性匿名內部類物件Java物件
- Java內部類詳解--匿名內部類Java
- 匿名內部類理解
- 物件導向之內部類物件
- java內部類之成員內部類之匿名內部類Java
- java內部類,區域性內部類,靜態內部類,匿名內部類Java
- 迴圈引用導致的json序列化失敗JSON
- Java內部類和匿名內部類的用法Java
- Java類與匿名內部類Java
- Drone構建失敗,一次drone依賴下載超時導致構建失敗的爬坑記錄
- 匿名內部類泛型泛型
- 匿名內部類方式實現執行緒的建立執行緒
- 10-Java內部類——成員內部類、區域性內部類、匿名內部類Java
- java培訓教程:什麼是匿名內部類?怎樣建立匿名內部類?Java
- Java基礎10---包、內部類、匿名內部類Java
- java之內部類(InnerClass)----非靜態內部類、靜態內部類、區域性內部類、匿名內部類Java
- Docker 導致阿里雲 ECS 內網互通失敗Docker阿里內網
- Java中的匿名內部類及內部類的二三事Java
- java匿名內部類:“ 儂好,世界”Java
- dotnet 記龍芯麒麟教育版安全中心攔截檔案 導致 docker 內 CI CD 構建失敗Docker
- JAVA物件導向基礎--N種內部類Java物件
- 匿名內部類中關於new Runnable ( )
- java中的匿名內部類總結Java
- Day 14 匿名函式 內建函式 物件導向程式設計函式物件程式設計
- dotnet 9 WPF 專案禁用 IncludePackageReferencesDuringMarkupCompilation 導致原始碼包 XAML 構建失敗Package原始碼
- 深入理解java巢狀類和內部類、匿名類Java巢狀
- Java_介面回撥與匿名內部類Java
- Java的特殊類用法:檔案類、內部類、本地類、匿名類Java
- 多執行緒-匿名內部類的方式實現多執行緒程式執行緒
- 小程式構建 npm 失敗NPM
- Filestream/Windows Share導致Alwayson Failover失敗WindowsAI
- 關於java匿名內部類初始化法Java
- 用匿名內部類實現 Java 同步回撥Java
- 記 Kylin 麒麟系統安全中心攔截導致 dotnet sdk 找不到 OpenSsl 構建失敗
- PHP 伺服器端內部業務處理失敗訊息傳遞方式PHP伺服器
- 故障分析 | DDL 導致的 Xtrabackup 備份失敗