writeObject

默认在不反射调用ObjectOutputStream创建实例的时候,调用writeObject0来处理
writeObject0内往下走会调用ObjectStreamClass.lookup方法进行处理

static ObjectStreamClass lookup(Class<?> cl, boolean all) {
if (!(all || Serializable.class.isAssignableFrom(cl))) { //判断对象实现了序列化接口没有
return null;
}
processQueue(Caches.localDescsQueue, Caches.localDescs);
WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue);
Reference<?> ref = Caches.localDescs.get(key);
Object entry = null;
if (ref != null) {
entry = ref.get();
}
EntryFuture future = null;
if (entry == null) {
EntryFuture newEntry = new EntryFuture();
Reference<?> newRef = new SoftReference<>(newEntry);
do {
if (ref != null) {
Caches.localDescs.remove(key, ref);
}
ref = Caches.localDescs.putIfAbsent(key, newRef);
if (ref != null) {
entry = ref.get();
}
} while (ref != null && entry == null);
if (entry == null) {
future = newEntry;
}
}
if (entry instanceof ObjectStreamClass) { // check common case first
return (ObjectStreamClass) entry;
}
if (entry instanceof EntryFuture) {
future = (EntryFuture) entry;
if (future.getOwner() == Thread.currentThread()) {
/*
* Handle nested call situation described by 4803747: waiting
* for future value to be set by a lookup() call further up the
* stack will result in deadlock, so calculate and set the
* future value here instead.
*/
entry = null;
} else {
entry = future.get();
}
}
if (entry == null) {
try {
entry = new ObjectStreamClass(cl); //最终会走到这里 跟入
} catch (Throwable th) {
entry = th;
}
if (future.set(entry)) {
Caches.localDescs.put(key, new SoftReference<Object>(entry));
} else {
// nested lookup call already set future
entry = future.get();
}
}
if (entry instanceof ObjectStreamClass) {
return (ObjectStreamClass) entry;
} else if (entry instanceof RuntimeException) {
throw (RuntimeException) entry;
} else if (entry instanceof Error) {
throw (Error) entry;
} else {
throw new InternalError("unexpected entry: " + entry);
}
}
首先会判断接口是否实现了序列化接口,然后会把WeakClassKey对象传入到localDescs去获取(map),最终会走到391行


先是获取类名 然后进行一些相关判断,是否是代理类 是否实现了序列化接口等
往下走会对序列化类的字段进行一些处理

这里是获取类中序列化类的私有字段serialVersionUID
在这里通过反射获取了类中的属性



往下走获取目标类中重写的方法,如readObject writeObject
在初始化完成后,回到writeObject0继续处理


先写入TC_OBJECT(115),然后往下就调用writeClassDesc

最终走到writeNonProxyDesc

writeClassDescriptor里面调用了writeNonProxy
void writeNonProxy(ObjectOutputStream out) throws IOException {
out.writeUTF(name);
out.writeLong(getSerialVersionUID());
byte flags = 0;
if (externalizable) {
flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
int protocol = out.getProtocolVersion();
if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
flags |= ObjectStreamConstants.SC_BLOCK_DATA;
}
} else if (serializable) {
flags |= ObjectStreamConstants.SC_SERIALIZABLE;
}
if (hasWriteObjectData) {
flags |= ObjectStreamConstants.SC_WRITE_METHOD;
}
if (isEnum) {
flags |= ObjectStreamConstants.SC_ENUM;
}
out.writeByte(flags);
out.writeShort(fields.length);
for (int i = 0; i < fields.length; i++) {
ObjectStreamField f = fields[i];
out.writeByte(f.getTypeCode());
out.writeUTF(f.getName());
if (!f.isPrimitive()) {
out.writeTypeString(f.getTypeString());
}
}
}
该方法主要就是写入类的一些信息 如名称 序列化的UID 字段信息
走完流程后接着回到writeOrdinaryObject方法

由于这里类不是代理类也没有实现Externalizable,所以会调writeSerialData

这里判断了用户有没有自己重写writeObject,如果有就调用用户自己写的,由于测试类没有重写,所以最终走到defaultWriteFields方法,在defaultWriteFields就是写入我们类字段的内容
下面是重写writeObject时候的处理


会通过反射调用用户自己创建的writeObject
