Java序列化Serializable源码

58 篇文章 0 订阅

先来看如何使用,再跟踪源码

目录

测试代码

数组对象是否深拷贝

serialVersionUID不一致

static变量是否序列化

自定义序列化内容

transient变量

Serializable 和 Externalizable接口

writeObject / readObject

writeReplace

readResolve

源码跟踪

new ObjectOutputStream/ ObjectInputStream

ObjectOutputStream.writeObject(user) 序列化

new ObjectStreamClass(Class cl)

writeArray()

writeOrdinaryObject

ObjectInputStream.readObject() 反序列化

序列化破坏单例模式的解决方案


测试代码

数组对象是否深拷贝

序列化和反序列化之后的两个对象是深拷贝,本例中user对象和内部的数组对象都是不同的

import java.io.Serializable;

public class User implements Serializable {

    private static final long serialVersionUID = 1101703620149581079L;
    private long long1;
    private int int2;
    private String str1;
    private String[] strArr = new String[5];

    public User(long long1, int int2, String str1) {
        this.long1 = long1;
        this.int2 = int2;
        this.str1 = str1;
    }

    public String toStirng() {
        return "long1:" + long1 + ", int2: " + int2 + ", str1: " + str1 + ", strArr:" + strArr;
    }
}


public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //序列化
        FileOutputStream fos = new FileOutputStream("object.out");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        User user1 = new User(1234534l, 12, "111111");
        System.out.println("序列化前对象值====" + user1.toStirng());
        oos.writeObject(user1);
        oos.flush();
        oos.close();

        //反序列化
        FileInputStream fis = new FileInputStream("object.out");
        ObjectInputStream ois = new ObjectInputStream(fis);
        User user2 = (User) ois.readObject();
        System.out.println("序列化后对象值====" + user2.toStirng());
    }
}

serialVersionUID不一致

表示类版本,序列化时,将类中UID输出到文件中,反序列化时会检查文件中的UID和 当前类中的UID,不一致则会报错不兼容。测试把对象序列化后改动UID,再反序列化,如下报错

Exception in thread "main" java.io.InvalidClassException: com.example.demo.Serializable.User; local class incompatible: stream classdesc serialVersionUID = 1101703620149581079, local class serialVersionUID = 1101703620149581071
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
	at com.example.demo.Serializable.Test.main(Test.java:22)

static变量是否序列化

public class User0 implements Serializable {

    private static final long serialVersionUID = 1101703620149581079L;
    private long long1;
    private int int2;
    private String str1;
    private static String static_str;

    public User0(long long1, int int2, String str1, String static_str) {
        this.long1 = long1;
        this.int2 = int2;
        this.str1 = str1;
        this.static_str = static_str;
    }

    public void setStatic(String sta) {
        static_str = sta;
    }

    public String toStirng() {
        return "long1:" + long1 + ", int2: " + int2 + ", str1: " + str1 + ", static_str: " + static_str;
    }
}

  public static void main(String[] args) throws IOException, ClassNotFoundException {
        //序列化
        FileOutputStream fos = new FileOutputStream("object.out");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        User0 user1 = new User0(1234534l, 12, "111111", "2222222");
        System.out.println("序列化前对象值====" + user1.toStirng());
        oos.writeObject(user1);
        oos.flush();
        oos.close();

        // 修改静态变量值
        user1.setStatic("444444");

        //反序列化
        FileInputStream fis = new FileInputStream("object.out");
        ObjectInputStream ois = new ObjectInputStream(fis);
        User0 user2 = (User0) ois.readObject();
        //反序列化的输出结果为:
        System.out.println("序列化后对象值====" + user2.toStirng());
    }
}

 可以看到,类变量和序列化无关

自定义序列化内容

上述代码将类中非static的对象都序列化到文件中,若想部分字段不参与序列化,或想自定义序列化方式,有三种方式

  • transient关键字修饰成员变量,则此变量不参与序列化
  • 实现Externalizable接口的writeExternal / readExternal方法,进行自定义
  • 对象存在private void 的writeObject / readObject方法,进行自定义

transient变量

public class User1 implements Serializable {

    private static final long serialVersionUID = 1101703620149581079L;
    private long long1;
    private int int2;
    private String str1;
    private transient String tran_str;

    public User1(long long1, int int2, String str1, String tran_str) {
        this.long1 = long1;
        this.int2 = int2;
        this.str1 = str1;
        this.tran_str = tran_str;
    }

    public String toStirng() {
        return "long1:" + long1 + ", int2: " + int2 + ", str1: " + str1 + ", tran_str: " + tran_str + "";
    }
}

 看到transient修饰的String变量未被序列化,值为null

Serializable 和 Externalizable接口

序列化必须实现 java.io.Serializable 接口,实现Serializable接口没有需要实现的接口方法,但若对象未实现Serializable接口,序列化时将会报错如下

Exception in thread "main" java.io.NotSerializableException: com.example.demo.Serializable.User
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
	at com.example.demo.Serializable.Test.main(Test.java:12)

 实现了Serializable接口的类的父类必须存在无参构造器,否则将会报错如下图,本例中User.java无父类,但是其实父类为Object.java, Object存在无参构造所以不会报错。

Externalizable接口实现了Serializable,并定义了两个方法,如下

import java.io.ObjectOutput;
import java.io.ObjectInput;

public interface Externalizable extends java.io.Serializable {
    void writeExternal(ObjectOutput out) throws IOException;
    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}

实现Externalizable方法,可以进行自定义需要序列化的字段和序列化方式,代码中将部分字段 还有 transient变量序列化

public class User2 implements Externalizable {

    private static final long serialVersionUID = 1101703620149581079L;
    private long long1;
    private int int2;
    private String str1;

    private transient String tran_str;
/*    public User2() {

    }*/

    public User2(long long1, int int2, String str1, String tran_str) {
        this.long1 = long1;
        this.int2 = int2;
        this.str1 = str1;
        this.tran_str = tran_str;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(str1);
        out.writeObject(tran_str);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.str1 = (String) in.readObject();
        this.tran_str = (String) in.readObject();
    }

    public String toStirng() {
        return "long1:" + long1 + ", int2: " + int2 + ", str1: " + str1 + ", tran_str: " + tran_str + "";
    }
}

运行发现报错如下,原因是实现了Externalizable接口的类必须存在无参构造

删除上边代码的注释再次运行,看到只有自定义的字段被序列化了,transient也不例外

writeObject / readObject

和Externalizable接口类似,不实现任何接口,在类中声明如下两个方法,即可实现自定义

private void writeObject(ObjectOutputStream out);
private void readObject(ObjectInputStream in);

public class User3 implements Serializable {

    private static final long serialVersionUID = 1101703620149581079L;
    private long long1;
    private int int2;
    private String str1;

    private transient String tran_str;

    public User3(long long1, int int2, String str1, String tran_str) {
        this.long1 = long1;
        this.int2 = int2;
        this.str1 = str1;
        this.tran_str = tran_str;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        // out.writeObject(str1);
        // out.writeObject("tututututu");
        // out.writeObject(tran_str);
        out.writeObject("1234234322");
        out.writeObject("999999999999");
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        this.str1 = (String) in.readObject();
        this.tran_str = (String) in.readObject();
    }

    public String toStirng() {
        return "long1:" + long1 + ", int2: " + int2 + ", str1: " + str1 + ", tran_str: " + tran_str + "";
    }
}

writeReplace

类中实现private Object writeReplace()方法,即可在序列化时,由方法返回的对象替换当前对象进行序列化

public class User4 implements Serializable {

    private static final long serialVersionUID = 1101703620149581071L;
    private long long1;
    private int int2;
    private String str1;
    private String[] strArr = new String[5];

    public User4(long long1, int int2, String str1) {
        this.long1 = long1;
        this.int2 = int2;
        this.str1 = str1;
    }

    private Object writeReplace() {
        return "fdsfsdfsdfs";
    }
    public String toStirng() {
        return "long1:" + long1 + ", int2: " + int2 + ", str1: " + str1 + ", strArr:" + strArr;
    }
}

 readResolve

类似writeReplace,类中实现private Object readResolve()方法,即ObjectInputStream.readObject()方法直接返回readResolve()方法返回的对象。可以用于防止单例模式被破坏,下边细讲

    private Object readResolve() {
        return "fdsfsdfsdfs";
    }

源码跟踪

new ObjectOutputStream/ ObjectInputStream

    public ObjectOutputStream(OutputStream out) throws IOException {
        verifySubclass();

        // 序列化数据流
        bout = new BlockDataOutputStream(out);

        // 缓存由本ObjectOutputStream序列化过的对象,如果非首次序列化,获取缓存索引值
        handles = new HandleTable(10, (float) 3.00);

        // 上文提到的writeReplace方式,缓存替换和被替换对象
        subs = new ReplaceTable(10, (float) 3.00);
        enableOverride = false;

        // 写 流的头数据
        writeStreamHeader();
        bout.setBlockDataMode(true);
        if (extendedDebugInfo) {
            debugInfoStack = new DebugTraceInfoStack();
        } else {
            debugInfoStack = null;
        }
    }

    public ObjectInputStream(InputStream in) throws IOException {
        verifySubclass();

        // 序列化数据流
        bin = new BlockDataInputStream(in);

        // 对象缓存
        handles = new HandleTable(10);
        vlist = new ValidationList();
        serialFilter = ObjectInputFilter.Config.getSerialFilter();
        enableOverride = false;
        
        // 读流的头数据
        readStreamHeader();
        bin.setBlockDataMode(true);
    }

可以看到,序列化和反序列化在 new ObjectOutputStream/ ObjectInputStream时就会写入和读取对象序列化数据头,再类中搜索了一下,没有发现其他地方调用writeStreamHeader或readStreamHeader,  那么就意味着,ObjectOutputStream/ ObjectInputStream对象 序列化和反序列化是一一对应的。要是每次序列化writeObject写入数据,使用不同的ObjectInputStream来读取,会报错,来测试一下。

简单的客户端和服务器端socket通信代码

public class server {
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        ServerSocket serverSocket = new ServerSocket(8080);
        Socket socket = serverSocket.accept();
        // ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
        while(true) {
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            Object o = ois.readObject();
            System.out.println(o);
        }
    }
}

public class client {
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket socket = new Socket("localhost", 8080);
        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        while (true) {
            //ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeObject("sadadasd");
            oos.flush();

            TimeUnit.SECONDS.sleep(2);
        }
    }
}

ObjectOutputStream/ ObjectInputStream一个在循环里,一个在循环外,即client用一个oos来写数据流,server端用多个ois来读,报错如下

上述代码应该是oos和ois要么都在循环里,要么都在循环外,一一对应

ObjectOutputStream.writeObject(user) 序列化

writeObject0()方法三部分

一、缓存查找是否已经处理过此对象 或对象为Class或ObjectStreamClass对象描述类,进行特殊处理

二、产生class对象的描述对象ObjectStreamClass,判断是否需要替换对象(writeReplace)

三、进行一般对象的处理,递归处理该对象

    public final void writeObject(Object obj) throws IOException {
        if (enableOverride) {// enableOverride 为 false
            writeObjectOverride(obj);
            return;
        }
        try {
            writeObject0(obj, false);
        } catch (IOException ex) {
            if (depth == 0) {
                writeFatalException(ex);
            }
            throw ex;
        }
    }

   private void writeObject0(Object obj, boolean unshared)
        throws IOException
    {
        boolean oldMode = bout.setBlockDataMode(false);
        depth++;
        try {
            // handle previously written and non-replaceable objects
            // 第一部分:处理已经处理过的对象(从缓存查找并处理)、和处理不可被替换的对象
            int h;
            if ((obj = subs.lookup(obj)) == null) {
                writeNull();
                return;
            } else if (!unshared && (h = handles.lookup(obj)) != -1) {
                writeHandle(h);
                return;
            } else if (obj instanceof Class) {
                writeClass((Class) obj, unshared);
                return;
            } else if (obj instanceof ObjectStreamClass) {
                writeClassDesc((ObjectStreamClass) obj, unshared);
                return;
            }

            // 第二部分:检查该对象是否需要被替换,本文提到的writeReplace
            Object orig = obj;// 保存源对象引用
            Class<?> cl = obj.getClass();// 保存源对象的class对象引用

            // 这个对象是class的序列化描述对象,内部保存元数据比如:类有哪些字段,有哪些方法,是否有writeObject等方法等等
            ObjectStreamClass desc;
            for (;;) {
                // REMIND: skip this check for strings/arrays?
                Class<?> repCl;
 
                // 根据class对象生成ObjectStreamClass描述对象
                desc = ObjectStreamClass.lookup(cl, true);

                // 1、该对象如果不存在writeReplace方法
                // 2、或者调用了writeReplace方法返回的对象为null
                // 3、或者调用writeReplace方法返回的对象是同类的对象
                // 那么使用刚才的ObjectStreamClass描述对象,否则需要根据替换对象的class重新产生ObjectStreamClass
                if (!desc.hasWriteReplaceMethod() ||
                    (obj = desc.invokeWriteReplace(obj)) == null ||
                    (repCl = obj.getClass()) == cl)
                {
                    break;
                }

                // 替换class对象,再循环查找新的对象是否存在writeReplace,重新产生ObjectStreamClass描述对象
                cl = repCl;
            }
            if (enableReplace) {
                Object rep = replaceObject(obj);
                if (rep != obj && rep != null) {
                    cl = rep.getClass();
                    desc = ObjectStreamClass.lookup(cl, true);
                }
                obj = rep;
            }

            // if object replaced, run through original checks a second time
            // 此时obj != orig,意味着对象已经被writeReplace替换了,重新走一遍 第一部分的处理
            if (obj != orig) {
                // subs中保存源对象和替换对象的对应关系,缓存,之后对相同对象的处理就直接查缓存
                subs.assign(orig, obj);
                if (obj == null) {
                    writeNull();
                    return;
                } else if (!unshared && (h = handles.lookup(obj)) != -1) {
                    writeHandle(h);
                    return;
                } else if (obj instanceof Class) {
                    writeClass((Class) obj, unshared);
                    return;
                } else if (obj instanceof ObjectStreamClass) {
                    writeClassDesc((ObjectStreamClass) obj, unshared);
                    return;
                }
            }

            // 剩余的对象,string array 枚举,实现了Serializable的对象的对应处理
            // 对其他没有实现Serializable的对象报错NotSerializableException
            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum<?>) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if (extendedDebugInfo) {
                    throw new NotSerializableException(
                        cl.getName() + "\n" + debugInfoStack.toString());
                } else {
                    throw new NotSerializableException(cl.getName());
                }
            }
        } finally {
            depth--;
            bout.setBlockDataMode(oldMode);
        }
    }

new ObjectStreamClass(Class<?> cl)

产生class对象的序列化描述对象ObjectStreamClass

   private ObjectStreamClass(final Class<?> cl) {
        this.cl = cl;
        // 类名        
        name = cl.getName();
        
        // 是否JDK代理产生的代理对象(继承Proxy类)
        isProxy = Proxy.isProxyClass(cl);

        // 是否是枚举类
        isEnum = Enum.class.isAssignableFrom(cl);

        // 是否实现了Serializable接口
        serializable = Serializable.class.isAssignableFrom(cl);

        // 是否实现了Externalizable接口
        externalizable = Externalizable.class.isAssignableFrom(cl);

        // 若存在超类,产生超类的描述对象ObjectStreamClass
        Class<?> superCl = cl.getSuperclass();
        superDesc = (superCl != null) ? lookup(superCl, false) : null;
        localDesc = this;

        if (serializable) {
            // 若实现了Serializable接口,判断可序列化字段等
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    // 若是枚举类,只序列化枚举对象名即可,不需序列化字段,serialVersionUID默认0
                    if (isEnum) {
                        suid = Long.valueOf(0);
                        fields = NO_FIELDS;
                        return null;
                    }
     
                    // 数组对象没有字段需要序列化,后续会循环数组对内部对象序列化
                   if (cl.isArray()) {
                        fields = NO_FIELDS;
                        return null;
                    }

                    // 获取serialVersionUID
                    suid = getDeclaredSUID(cl);
                    try {
                        // 获取可序列化的字段,获取所有字段,排除static和transient所修饰的
                        fields = getSerialFields(cl);

                        // 计算各字段序列化顺序,得到各字段的序列化偏移量
                        // 反序列化时,根据这个偏移量来从流中获取某一段的字节并设置为对应的属性值
                        computeFieldOffsets();
                    } catch (InvalidClassException e) {
                        serializeEx = deserializeEx =
                            new ExceptionInfo(e.classname, e.getMessage());
                        fields = NO_FIELDS;
                    }

                   
                    if (externalizable) {
                        // 若实现了Externalizable ,获取无参构造器
                        cons = getExternalizableConstructor(cl);
                    } else {
                        // 获取序列化对象父类的无参构造器
                        cons = getSerializableConstructor(cl);

                        // 自定义的序列化方法writeObject/readObject,readObjectNoData
                        writeObjectMethod = getPrivateMethod(cl, "writeObject",
                            new Class<?>[] { ObjectOutputStream.class },
                            Void.TYPE);
                        readObjectMethod = getPrivateMethod(cl, "readObject",
                            new Class<?>[] { ObjectInputStream.class },
                            Void.TYPE);
                        readObjectNoDataMethod = getPrivateMethod(
                            cl, "readObjectNoData", null, Void.TYPE);
                        hasWriteObjectData = (writeObjectMethod != null);
                    }
                    // 这不知道
                    domains = getProtectionDomains(cons, cl);
                    
                    // 上边提到过的替换对象相关的两个方法
                    writeReplaceMethod = getInheritableMethod(
                        cl, "writeReplace", null, Object.class);
                    readResolveMethod = getInheritableMethod(
                        cl, "readResolve", null, Object.class);
                    return null;
                }
            });
        } else {
            suid = Long.valueOf(0);
            fields = NO_FIELDS;
        }

        try {
            // 各字段Field的引用,似乎是用来反序列化时设置字段的值
            fieldRefl = getReflector(fields, this);
        } catch (InvalidClassException ex) {
            // field mismatches impossible when matching local fields vs. self
            throw new InternalError(ex);
        }

        if (deserializeEx == null) {
            if (isEnum) {
                deserializeEx = new ExceptionInfo(name, "enum type");
            } else if (cons == null) {
                deserializeEx = new ExceptionInfo(name, "no valid constructor");
            }
        }
        for (int i = 0; i < fields.length; i++) {
            if (fields[i].getField() == null) {
                defaultSerializeEx = new ExceptionInfo(
                    name, "unmatched serializable field(s) declared");
            }
        }

        // 初始化 ObjectStreamClass完毕
        initialized = true;
    }

writeArray()

先看个简单的数组对象序列化方法,内部判断数组存的是基本数据类型还是引用类型,基本数据类型直接写字节数据,引用类型则需递归调用writeObject0方法序列化

   private void writeArray(Object array,
                            ObjectStreamClass desc,
                            boolean unshared)
        throws IOException
    {
        // 流中写入数组对象的描述类信息desc
        bout.writeByte(TC_ARRAY);
        writeClassDesc(desc, false);

        // 写入缓存
        handles.assign(unshared ? null : array);

        // 如果数组对象中存得是基本数据类型,写入int long等数据
        Class<?> ccl = desc.forClass().getComponentType();
        if (ccl.isPrimitive()) {
            if (ccl == Integer.TYPE) {
                int[] ia = (int[]) array;
                bout.writeInt(ia.length);
                bout.writeInts(ia, 0, ia.length);
            } else if (ccl == Byte.TYPE) {
                byte[] ba = (byte[]) array;
                bout.writeInt(ba.length);
                bout.write(ba, 0, ba.length, true);
            } else if (ccl == Long.TYPE) {
                long[] ja = (long[]) array;
                bout.writeInt(ja.length);
                bout.writeLongs(ja, 0, ja.length);
            } else if (ccl == Float.TYPE) {
                float[] fa = (float[]) array;
                bout.writeInt(fa.length);
                bout.writeFloats(fa, 0, fa.length);
            } else if (ccl == Double.TYPE) {
                double[] da = (double[]) array;
                bout.writeInt(da.length);
                bout.writeDoubles(da, 0, da.length);
            } else if (ccl == Short.TYPE) {
                short[] sa = (short[]) array;
                bout.writeInt(sa.length);
                bout.writeShorts(sa, 0, sa.length);
            } else if (ccl == Character.TYPE) {
                char[] ca = (char[]) array;
                bout.writeInt(ca.length);
                bout.writeChars(ca, 0, ca.length);
            } else if (ccl == Boolean.TYPE) {
                boolean[] za = (boolean[]) array;
                bout.writeInt(za.length);
                bout.writeBooleans(za, 0, za.length);
            } else {
                throw new InternalError();
            }
        } else {
            // 是引用对象数组
            Object[] objs = (Object[]) array;
            int len = objs.length;
            bout.writeInt(len);
            if (extendedDebugInfo) {
                debugInfoStack.push(
                    "array (class \"" + array.getClass().getName() +
                    "\", size: " + len  + ")");
            }
            try {
                // 循环数组,递归调用writeObject0 序列化
                for (int i = 0; i < len; i++) {
                    if (extendedDebugInfo) {
                        debugInfoStack.push(
                            "element of array (index: " + i + ")");
                    }
                    try {
                        writeObject0(objs[i], false);
                    } finally {
                        if (extendedDebugInfo) {
                            debugInfoStack.pop();
                        }
                    }
                }
            } finally {
                if (extendedDebugInfo) {
                    debugInfoStack.pop();
                }
            }
        }
    }

 writeOrdinaryObject

对实现了Serializable接口的类进行序列化的方法

   private void writeOrdinaryObject(Object obj,
                                     ObjectStreamClass desc,
                                     boolean unshared)
        throws IOException
    {
        try {
            desc.checkSerialize();

            // 写入Object类型标识,接着写入class描述对象ObjectStreamClass 
            bout.writeByte(TC_OBJECT);
            writeClassDesc(desc, false);

            // 写入缓存
            handles.assign(unshared ? null : obj);
            if (desc.isExternalizable() && !desc.isProxy()) {
                // 如果实现的是Externalizable接口,调用接口方法进行序列化
                writeExternalData((Externalizable) obj);
            } else {
                // 一般走这
                writeSerialData(obj, desc);
            }
        } finally {
            if (extendedDebugInfo) {
                debugInfoStack.pop();
            }
        }
    }

java.io.ObjectOutputStream#writeExternalData

   private void writeExternalData(Externalizable obj) throws IOException {
        // 删除了部分
         bout.setBlockDataMode(true);
         obj.writeExternal(this);
          bout.setBlockDataMode(false);
          bout.writeByte(TC_ENDBLOCKDATA);
    }

java.io.ObjectOutputStream#writeSerialData

if...else...两块,如果实现了writeObject方法,调用writeObject写数据,否则默认操作

    private void writeSerialData(Object obj, ObjectStreamClass desc)
        throws IOException
    {
        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
        for (int i = 0; i < slots.length; i++) {
            ObjectStreamClass slotDesc = slots[i].desc;
            if (slotDesc.hasWriteObjectMethod()) {
                PutFieldImpl oldPut = curPut;
                curPut = null;
                SerialCallbackContext oldContext = curContext;

                try {
                    curContext = new SerialCallbackContext(obj, slotDesc);
                    bout.setBlockDataMode(true);
                    slotDesc.invokeWriteObject(obj, this);
                    bout.setBlockDataMode(false);
                    bout.writeByte(TC_ENDBLOCKDATA);
                } finally {
                    curContext.setUsed();
                    curContext = oldContext;
                    if (extendedDebugInfo) {
                        debugInfoStack.pop();
                    }
                }

                curPut = oldPut;
            } else {
                defaultWriteFields(obj, slotDesc);
            }
        }
    }


   private void defaultWriteFields(Object obj, ObjectStreamClass desc)
        throws IOException
    {
        Class<?> cl = desc.forClass();
        if (cl != null && obj != null && !cl.isInstance(obj)) {
            throw new ClassCastException();
        }

        desc.checkDefaultSerialize();

        // 获取基本数据类型共占用多少字节大小
        int primDataSize = desc.getPrimDataSize();
        if (primVals == null || primVals.length < primDataSize) {
            primVals = new byte[primDataSize];
        }
        // 根据描述对象 将基本数据类型按 顺序写入btye数组中
        // 顺序在new ObjectStreamClass().computeFieldOffsets() 计算;
        desc.getPrimFieldValues(obj, primVals);

        // 将字节数组写入流
        bout.write(primVals, 0, primDataSize, false);

        // 再序列化引用类型
        // 获取对象中需要序列化的字段数
        ObjectStreamField[] fields = desc.getFields(false);

        // 声明一个对象数组,大小为引用类型字段数
        Object[] objVals = new Object[desc.getNumObjFields()];

        // numPrimFields 为基本数据类型字段数(总-引用类型数)
        int numPrimFields = fields.length - objVals.length;

        // 获取对象的引用类型字段值
        desc.getObjFieldValues(obj, objVals);
        for (int i = 0; i < objVals.length; i++) {
            try {
               // 递归调用writeObject0方法序列化
                writeObject0(objVals[i],
                             fields[numPrimFields + i].isUnshared());
            } finally {
                if (extendedDebugInfo) {
                    debugInfoStack.pop();
                }
            }
        }
    }

ObjectInputStream.readObject() 反序列化

序列化时,每次会先写入当前对象的类型(一个字节),其次写入该对象的描述ObjectStreamClass类,再写入对象的各字段数据,反序列化时反向来一遍,读类型、读class描述类、再根据描述类按顺序读取各个字段值

下边的分支,本文只看Object类型

   private Object readObject0(boolean unshared) throws IOException {
        // 搂一眼第一个字节,即对象的类型,是字符串还是数组还是对象
        byte tc;
        while ((tc = bin.peekByte()) == TC_RESET) {
            bin.readByte();
            handleReset();
        }

        depth++;
        totalObjectRefs++;
        try {
            // 根据第一个字节是什么,来判断走哪个处理分支
            switch (tc) {
                case TC_NULL:
                    return readNull();

                case TC_REFERENCE:
                    return readHandle(unshared);

                case TC_CLASS:
                    return readClass(unshared);

                case TC_CLASSDESC:
                case TC_PROXYCLASSDESC:
                    return readClassDesc(unshared);

                case TC_STRING:
                case TC_LONGSTRING:
                    return checkResolve(readString(unshared));

                case TC_ARRAY:
                    return checkResolve(readArray(unshared));

                case TC_ENUM:
                    return checkResolve(readEnum(unshared));

                case TC_OBJECT:
                    return checkResolve(readOrdinaryObject(unshared));

                case TC_EXCEPTION:
                    IOException ex = readFatalException();
                    throw new WriteAbortedException("writing aborted", ex);

                case TC_BLOCKDATA:
                case TC_BLOCKDATALONG:
                    if (oldMode) {
                        bin.setBlockDataMode(true);
                        bin.peek();             // force header read
                        throw new OptionalDataException(
                            bin.currentBlockRemaining());
                    } else {
                        throw new StreamCorruptedException(
                            "unexpected block data");
                    }

                case TC_ENDBLOCKDATA:
                    if (oldMode) {
                        throw new OptionalDataException(true);
                    } else {
                        throw new StreamCorruptedException(
                            "unexpected end of block data");
                    }

                default:
                    throw new StreamCorruptedException(
                        String.format("invalid type code: %02X", tc));
            }
        } finally {
            depth--;
            bin.setBlockDataMode(oldMode);
        }
    }
    private Object readOrdinaryObject(boolean unshared)
        throws IOException
    {
        // 第一个字节,须为Object类型
        if (bin.readByte() != TC_OBJECT) {
            throw new InternalError();
        }

        // 读ObjectStreamClass 类
        ObjectStreamClass desc = readClassDesc(false);
        desc.checkDeserialize();

        Class<?> cl = desc.forClass();
        if (cl == String.class || cl == Class.class
                || cl == ObjectStreamClass.class) {
            throw new InvalidClassException("invalid class descriptor");
        }

        // 用解析出的无参构造函数,new一个空对象
        Object obj;
        try {
            obj = desc.isInstantiable() ? desc.newInstance() : null;
        } catch (Exception ex) {
            throw (IOException) new InvalidClassException(
                desc.forClass().getName(),
                "unable to create instance").initCause(ex);
        }

        // 缓存
        passHandle = handles.assign(unshared ? unsharedMarker : obj);
        ClassNotFoundException resolveEx = desc.getResolveException();
        if (resolveEx != null) {
            handles.markException(passHandle, resolveEx);
        }

        // 根据实现的接口,走不同的解析路子
        if (desc.isExternalizable()) {
            // 自定义实现的readExternal方法读取数据流
            readExternalData((Externalizable) obj, desc);
        } else {
            // 若有readObject方法,使用此方法读取
            // 若没有,看下文
            readSerialData(obj, desc);
        }

        handles.finish(passHandle);

        // 判断是否存在readResolve方法,如果有,调用并替换对象,return
        if (obj != null &&
            handles.lookupException(passHandle) == null &&
            desc.hasReadResolveMethod())
        {
            Object rep = desc.invokeReadResolve(obj);
            if (unshared && rep.getClass().isArray()) {
                rep = cloneArray(rep);
            }
            if (rep != obj) {
                // Filter the replacement object
                if (rep != null) {
                    if (rep.getClass().isArray()) {
                        filterCheck(rep.getClass(), Array.getLength(rep));
                    } else {
                        filterCheck(rep.getClass(), -1);
                    }
                }
                handles.setObject(passHandle, obj = rep);
            }
        }

        return obj;
    }

默认的读取对象规则

    private void defaultReadFields(Object obj, ObjectStreamClass desc)
        throws IOException
    {
        Class<?> cl = desc.forClass();
        if (cl != null && obj != null && !cl.isInstance(obj)) {
            throw new ClassCastException();
        }

        // 从ObjectStreamClass 对象获取基本数据类型大小
        int primDataSize = desc.getPrimDataSize();
        if (primVals == null || primVals.length < primDataSize) {
            primVals = new byte[primDataSize];
        }
           // 读取相应大小的字节到数组中
            bin.readFully(primVals, 0, primDataSize, false);
        if (obj != null) {
            // 按顺序设置到对象属性中
            desc.setPrimFieldValues(obj, primVals);
        }

        // 获取引用类型的属性,递归readObject0方法
        int objHandle = passHandle;
        ObjectStreamField[] fields = desc.getFields(false);
        Object[] objVals = new Object[desc.getNumObjFields()];
        int numPrimFields = fields.length - objVals.length;
        for (int i = 0; i < objVals.length; i++) {
            ObjectStreamField f = fields[numPrimFields + i];
            objVals[i] = readObject0(f.isUnshared());
            if (f.getField() != null) {
                handles.markDependency(objHandle, passHandle);
            }
        }

        // 设置引用类型的值
        if (obj != null) {
            desc.setObjFieldValues(obj, objVals);
        }
        passHandle = objHandle;
    }

序列化破坏单例模式的解决方案

利用readResolve方法替换序列化对象的操作,实现readResolve方法,返回单例对象,代码示例如下

public class Singleton2 implements Serializable{

    private static final long serialVersionUID = 2855907098089861400L;

    private static Singleton2 instance = new Singleton2();
    private Singleton2() {}

    private Object readResolve() {
        return instance;
    }

    public static Singleton2 getInstance() {
        return instance;
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileOutputStream fos = new FileOutputStream("instance.out");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        Singleton2 instance = Singleton2.getInstance();
        oos.writeObject(instance);
        oos.flush();
        oos.close();

        //反序列化
        FileInputStream fis = new FileInputStream("instance.out");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object obj = ois.readObject();
        Singleton2 instance2 = (Singleton2) obj;
        System.out.println(instance == instance2);
    }
}

 执行为true,表示为同对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值