[Java基礎(chǔ)]關(guān)于Java序列化從0到1

序列化最基本使用


public class A implements Serializable{
    private static final long serialVersionUID = 9175036933185692367L;
    private final String name;
    private String Id;
    public A(String name,String Id){
        this.name = name;
        this.Id = Id;
    }    public void methodA(){
        System.out.println("My name is zazalu" + Id);
    }
}

class B{
    public static void main(String[] args) throws IOException {
        //將A序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("test.txt")));
        A a = new A("zazaluA","123456");
        oos.writeObject(a);
    }
}

class C{
    //將A反序列化
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("test.txt")));
        A a = (A) ois.readObject();
        a.methodA();    //輸出My name is zazalu123456
    }
}

以上就是最基本的序列化使用方式政模,不多說堕伪。接下來來思考Serializable到底在底層發(fā)生了什么

其實弹沽,上面的代碼其實隱式調(diào)用了2個方法

private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

接下來我們來演示下窜锯,將這兩個方法在A類中重寫

private void readObject(ObjectInputStream in){
    System.out.println("調(diào)用了readObject");
}
private void writeObject(java.io.ObjectOutputStream out){
    System.out.println("調(diào)用了writeObject");
}

然后我們在此運行下熏挎,控制臺輸出就變成了這樣:


Paste_Image.png
Paste_Image.png

可見蚌成,這兩個方法都被調(diào)用了前痘。

那么接下來我們就要學習這兩個方法到底可以做什么?

首先我們先了解下下面兩個方法

in.defaultReadObject(); 
out.defaultWriteObject(); //in和out是對象輸入輸出流的兩個實例

這兩個方法其實是對象流讀寫對象的默認的底層調(diào)用方法担忧。
當我們使用out.writeObject()和in.readObject()的時候芹缔,就會默認去調(diào)用

in.defaultReadObject(); 
out.defaultWriteObject(); 

這兩個方法是會把允許序列化的屬性和方法進行序列化和反序列化(被transient關(guān)鍵字修飾的屬性方法是不會被默認序列化的)


既然

in.defaultReadObject(); 
out.defaultWriteObject(); 

這兩個是默認的方法,那么看來我們可以自定義序列化過程
如何自定義序列化瓶盛,其實方法有很多
主要是使用

private void readObject(ObjectInputStream in){
    System.out.println("只反序列化Id屬性");
    out.writeObject(Id);
}
private void writeObject(java.io.ObjectOutputStream out){
    System.out.println("只序列化Id屬性");
    this.Id = in.readObject();
}

在序列化的類中重寫這兩個方法進行自定義序列化最欠!上述寫法就只序列化了一個Id屬性示罗,而name屬性沒有序列化!

但是我們這樣自定義序列化是很粗糙的芝硬,因為我們沒有處理很多細節(jié)方法的問題蚜点,比如NotActiveException我們就沒有做處理。所以我們最好是

in.defaultReadObject(); 
out.defaultWriteObject(); 

讓這兩個方法被調(diào)用吵取。所以我們可以如此實現(xiàn)
1.先將所有屬性方法喲哦那個transient關(guān)鍵字修飾
2.將你想要序列化的字段用out.writeObject()和in.readObject()來實現(xiàn)
3.在最后調(diào)用in.defaultReadObject(); 和in.defaultReadObject(); 來保證細節(jié)處理正常

private void readObject(ObjectInputStream in){
    System.out.println("只反序列化Id屬性");
    out.writeObject(Id);
    in.defaultReadObject();  
}
private void writeObject(java.io.ObjectOutputStream out){
    System.out.println("只序列化Id屬性");
    this.Id = in.readObject();
    in.defaultReadObject(); 
}


序列化安全問題


1.首先禽额,序列化出來的字節(jié)流,可以進行分析皮官,從而給攻擊者暴露了所有的信息脯倒,解決方法:在序列化時對字段進行加密,反序列化的時候再進行解密
2.其次捺氢,攻擊者可以偽造字節(jié)流藻丢,然后通過反序列化獲取珍貴的信息。
比如(Period是一個類摄乒,有start和end這兩個Date屬性)

ByteArrayOutputStream bos = new ByteArrayOutputStream();  
ObjectOutputStream oos = new ObjectOutputStream(/*new FileOutputStream(new File("D:/obj.data"))*/bos);  
oos.writeObject(new Period(new Date(), new Date()));  
/*
偽造一個字節(jié)流悠反,這個字節(jié)流以一個有效的Period實例所產(chǎn)生的字節(jié)流作為開始,然后附加上兩個額外的引用馍佑,指向Period實例中的兩個內(nèi)部私有Date域斋否,攻擊者通過引用攻擊內(nèi)部域
*/          
byte[] ref = {0x71, 0 , 0x7e, 0, 5};  
bos.write(ref);  
ref[4] = 4;  
bos.write(ref);  
          
ObjectInputStream ois = new ObjectInputStream(/*new FileInputStream(new File("D:/obj.data"))*/new ByteArrayInputStream(bos.toByteArray()));  
period = (Period)ois.readObject();  
start = (Date)ois.readObject();  //獲取到了Period里的start屬性引用
end = (Date)ois.readObject();  //獲取到了Period里的end屬性引用

......
//獲取到的end屬性,我們可以修改拭荤,因為是對象類型茵臭,所以period里的end屬性也發(fā)生了變化!這實在是太惡毒了
end.setYear(78); 

解決辦法:使用保護性拷貝舅世!

private void readObject(java.io.ObjectInputStream in)

 throws IOException, ClassNotFoundException{

 in.defaultReadObject();

 start = new Date(start.getTime());

 end = new Date(end.getTime()); //重新創(chuàng)建start和end對象引用

 }

可是這辦法因為二次修改了屬性的引用旦委,所以無法和final字段配合使用,更多時候我們會希望屬性是final的雏亚,這樣就不會被輕易修改了缨硝。

加強解決辦法:使用序列化代理

序列化代理


http://blog.csdn.net/drifterj/article/details/7802586
參看這個bolg,寫的非常具體了罢低!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末查辩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子网持,更是在濱河造成了極大的恐慌宜肉,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翎碑,死亡現(xiàn)場離奇詭異,居然都是意外死亡之斯,警方通過查閱死者的電腦和手機日杈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門遣铝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人莉擒,你說我怎么就攤上這事酿炸。” “怎么了涨冀?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵填硕,是天一觀的道長。 經(jīng)常有香客問我鹿鳖,道長扁眯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任翅帜,我火速辦了婚禮姻檀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涝滴。我一直安慰自己绣版,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布歼疮。 她就那樣靜靜地躺著杂抽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪韩脏。 梳的紋絲不亂的頭發(fā)上缩麸,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音骤素,去河邊找鬼匙睹。 笑死,一個胖子當著我的面吹牛济竹,可吹牛的內(nèi)容都是我干的痕檬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼送浊,長吁一口氣:“原來是場噩夢啊……” “哼梦谜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起袭景,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤唁桩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后耸棒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荒澡,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年与殃,在試婚紗的時候發(fā)現(xiàn)自己被綠了单山。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碍现。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖米奸,靈堂內(nèi)的尸體忽然破棺而出昼接,到底是詐尸還是另有隱情,我是刑警寧澤悴晰,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布慢睡,位于F島的核電站,受9級特大地震影響铡溪,放射性物質(zhì)發(fā)生泄漏漂辐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一佃却、第九天 我趴在偏房一處隱蔽的房頂上張望者吁。 院中可真熱鬧,春花似錦饲帅、人聲如沸复凳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽育八。三九已至,卻和暖如春赦邻,著一層夾襖步出監(jiān)牢的瞬間髓棋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工惶洲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留按声,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓恬吕,卻偏偏與公主長得像签则,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铐料,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • JAVA序列化機制的深入研究 對象序列化的最主要的用處就是在傳遞,和保存對象(object)的時候,保證對象的完整...
    時待吾閱讀 10,864評論 0 24
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理渐裂,服務(wù)發(fā)現(xiàn),斷路器钠惩,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 官方文檔理解 要使類的成員變量可以序列化和反序列化柒凉,必須實現(xiàn)Serializable接口。任何可序列化類的子類都是...
    獅_子歌歌閱讀 2,411評論 1 3
  • 一篓跛、 序列化和反序列化概念 Serialization(序列化)是一種將對象以一連串的字節(jié)描述的過程膝捞;反序列化de...
    步積閱讀 1,443評論 0 10
  • 十一:DataBinding頁面解析json出現(xiàn)數(shù)據(jù)異常 重要提醒:由于我這個版本先后更新了umeng/udesk...
    夏廣成閱讀 405評論 0 0