1、源码分析Kryo#writeClassAndObject
public void writeClassAndObject (Output output, Object object) {
if (output == null) throw new IllegalArgumentException(“output cannot be null.”);
beginObject(); // @1
try {
if (object == null) {
writeClass(output, null); // @2
return;
}
Registration registration = writeClass(output, object.getClass()); // @3
if (references && writeReferenceOrNull(output, object, false)) { // @4
registration.getSerializer().setGener
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
ics(this, null);
return;
}
if (TRACE || (DEBUG && depth == 1)) log(“Write”, object);
registration.getSerializer().write(this, output, object); // @5
} finally {
if (–depth == 0 && autoReset) reset(); // @6
}
}
代码@1:开始序列化, 将dept自增,表示当前深度,因为在序列化一个对象时,该方法有可能会被递归调用,每递归调用增加1,一次调用结束后在finally字句中自减。
代码@2:如果对象为空,则调用writeClass(DefaultSerializers$ClassSerializer),序列化为空。
代码@3:如果对象不为空,首先序列化对象所属的Class实例,从这里可以看出,Kryo在序列化时,首先先序列化类型。
代码@4:如果references 为true(默认为true,可以序列化循环依赖),则调用writeReferenceOrNull序列化。
代码@5:如果references 为false,则调用write序列化,此时如果对象存在循环依赖,则会抛出 throw new KryoException("Max depth exceeded: " + depth)异常,如果object为基本类型,也将通过该方法完成值的序列化。
代码@6:完成序列化后,恢复相关数据。也就是说Kryo实例并不是线程安全的。
默认references 为true,表示支持循环嵌套,我们接下来重点跟踪一下writeReferenceOrNull方法。
1.1 源码分析writeReferenceOrNull方法
/** @param object May be null if mayBeNull is true.
- @return true if no bytes need to be written for the object. */
boolean writeReferenceOrNull (Output output, Object object, boolean mayBeNull) { // @1
if (object == null) { // @2
if (TRACE || (DEBUG && depth == 1)) log(“Write”, null);
output.writeVarInt(Kryo.NULL, true);
return true;
}
if (!referenceResolver.useReferences(object.getClass())) { // @3
if (mayBeNull) output.writeVarInt(Kryo.NOT_NULL, true);
return false;
}
// Determine if this object has already been seen in this object graph.
int id = referenceResolver.getWrittenId(object); // @4
// If not the first time encountered, only write reference ID.
if (id != -1) { // @5
if (DEBUG) debug(“kryo”, "Write object reference " + id + ": " + string(object));
output.writeVarInt(id + 2, true); // + 2 because 0 and 1 are used for NULL and NOT_NULL.
return true;
}
// Otherwise write NOT_NULL and then the object bytes.
id = referenceResolver.addWrittenObject(object); // @6
output.writeVarInt(NOT_NULL, true);
if (TRACE) trace(“kryo”, "Write initial object reference " + id + ": " + string(object));
return false; // @7
}
代码@1:参数说明:Output output:输出流;Object object:待序列化的对象;
代码@2:如果对象为空,写入Kryo.NULL(0),然后返回true,表示需要设置generic,后续会讲解一下generic(泛型支持)。
代码@3:如果是基本类型,如果maybe(值可能为空),但该方法不为空,则设置为Kryo.NOT_NULL,然后返回false,表示非引用类型,需要持久化值。
代码@4:判断该对象是否在对象图中已被序列化一次。(其实现方式ListReferenceResolver、MapReferenceResolver)。
ListReferenceResolver#getWrittenId
public int getWrittenId (Object object) {
for (int i = 0, n = seenObjects.size(); i < n; i++) {
if (seenObjects.get(i) == object) {
return i;
}
}
return -1;
}