learn
How to use it?
简单地建一个User
类 并添加 set
、get
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package com.xmldecode;
public class User { private String Name; private String Sex; private int Age;
public User() { System.out.println("Constructor has called"); }
public User(String name, String sex, int age) { System.out.println("有参构造方法被调用"); this.Name = name; this.Sex = sex; this.Age = age; }
public void setName(String name) { System.out.println("setName has called"); this.Name = name; }
public void setSex(String sex) { System.out.println("setSex has called"); this.Sex = sex; }
public void setAge(int age) { System.out.println("setAge has called"); this.Age = age; }
public int getAge() { System.out.println("getAge has called"); return this.Age; }
public String getSex() { System.out.println("getSex has called"); return this.Sex; }
public String getName() { System.out.println("getName has called"); return this.Name; }
@Override public String toString(){ return "User{" + "Name='" + Name + "'" + ", Sex='" + Sex + "'" + ", Age=" + Age + "}"; } }
|
来encode一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.xmldecode;
import java.beans.XMLEncoder; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream;
public class testDecode {
public static void main(String[] args) { User user = new User(); user.setAge(20); user.setName("b1ue0cean"); user.setSex("man");
try { XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream( new FileOutputStream("User.xml") ));
encoder.writeObject(user); encoder.close(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } }
}
|
生成了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_202" class="java.beans.XMLDecoder"> <object class="com.xmldecode.User"> <void property="age"> <int>20</int> </void> <void property="name"> <string>b1ue0cean</string> </void> <void property="sex"> <string>man</string> </void> </object> </java>
|
控制台
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Constructor has called setAge has called setName has called setSex has called Constructor has called getAge has called getAge has called getAge has called setAge has called getName has called getName has called setName has called getSex has called getSex has called setSex has called
|
XMLEncoder默认会在序列化时调⽤⽆参构造⽅法以及属性的 get 和 set ⽅法,并且还存在多次调⽤的情况。
XMLDecoder Deserialize
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.xmldecode;
import java.beans.XMLDecoder; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException;
public class deserialize { public static void main(String[] args) { XMLDecoder xmlDecoder = null; try { xmlDecoder = new XMLDecoder( new BufferedInputStream( new FileInputStream("User.xml") ) ); } catch (FileNotFoundException e) { throw new RuntimeException(e); } Object result = xmlDecoder.readObject(); xmlDecoder.close(); System.out.println(result); } }
|
控制台
1 2 3 4 5
| Constructor has called setAge has called setName has called setSex has called User
|
反序列化默认情况下会调⽤属性中的 set ⽅法
Analysis
主要分析一下 readObject
先弹一个计算器 o.o
1 2 3 4 5 6 7 8 9 10
| <java> <object class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1" > <void index="0"> <string>calc</string> </void> </array> <void method="start"/> </object> </java>
|
把刚才deserialize 的文件改一下就行 真弹了计算器o.o
下断点
跟进 readObject()
不知道为啥可以从堆栈里看,,,这个调试我也不是很熟 估计等会要找点文章学学
跟进persingComplete()
this.Handler 为 documentHandler
parse()
注意看这里
我们关注DocumentHandler的几个事件函数
对应了com.sun.beans.decoder
包中的几个类
接着 看一下 SAX 的处理过程
这几个 set 都要走一遍
这里y4er god中间省略了亿步。。。搞得我蒙了半天
看调用栈可以看出 这里已经跟进了亿步的 parse
中间跳过亿步
。
。
。
最后通过Expression的getValue()方法反射调用start
emmm 所以跟了这么久好像也没啥用 o.o
reference
XMLDecoder解析流程分析 - 先知社区 (aliyun.com)
https://zhuanlan.zhihu.com/p/350309128