java序列化和反序列化源码分析

990 阅读5分钟

序列化

ObjectOutputStream

核心步骤

1、把对象转换为二进制

/**
 * Write the specified object to the ObjectOutputStream.  The class of the
 * object, the signature of the class, and the values of the non-transient
 * and non-static fields of the class and all of its supertypes are
 * written.  Default serialization for a class can be overridden using the
 * writeObject and the readObject methods.  Objects referenced by this
 * object are written transitively so that a complete equivalent graph of
 * objects can be reconstructed by an ObjectInputStream.
 *
 * <p>Exceptions are thrown for problems with the OutputStream and for
 * classes that should not be serialized.  All exceptions are fatal to the
 * OutputStream, which is left in an indeterminate state, and it is up to
 * the caller to ignore or recover the stream state.
 *
 * @throws  InvalidClassException Something is wrong with a class used by
 *          serialization.
 * @throws  NotSerializableException Some object to be serialized does not
 *          implement the java.io.Serializable interface.
 * @throws  IOException Any exception thrown by the underlying
 *          OutputStream.
 */
public final void writeObject(Object obj) throws IOException {
    if (enableOverride) {
        writeObjectOverride(obj);
        return;
    }
    try {
        writeObject0(obj, false); //调用底层方法
    } catch (IOException ex) {
        if (depth == 0) {
            writeFatalException(ex);
        }
        throw ex;
    }
}

核心步骤

  1. 校验对象的类型
  2. 如果是普通对象,就调用writeOrdinaryObject方法
/**
 * Underlying writeObject/writeUnshared implementation.
 */
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;
        }

        // check for replacement object
        Object orig = obj;
        Class<?> cl = obj.getClass();
        ObjectStreamClass desc;
        for (;;) {
            // REMIND: skip this check for strings/arrays?
            Class<?> repCl;
            desc = ObjectStreamClass.lookup(cl, true);
            if (!desc.hasWriteReplaceMethod() ||
                (obj = desc.invokeWriteReplace(obj)) == null ||
                (repCl = obj.getClass()) == cl)
            {
                break;
            }
            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
        if (obj != orig) {
            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;
            }
        }

        // remaining cases //处理剩下的情况
        //校验对象的类型
        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);
    }
}

核心步骤

  1. 写类描述信息
  2. 把对象转换为二进制
/**
 * Writes representation of a "ordinary" (i.e., not a String, Class,
 * ObjectStreamClass, array, or enum constant) serializable object to the
 * stream.
 */
private void writeOrdinaryObject(Object obj,
                                 ObjectStreamClass desc,
                                 boolean unshared)
    throws IOException
{
    if (extendedDebugInfo) {
        debugInfoStack.push(
            (depth == 1 ? "root " : "") + "object (class "" +
            obj.getClass().getName() + "", " + obj.toString() + ")");
    }
    try {
        desc.checkSerialize();

        bout.writeByte(TC_OBJECT);
        //写类描述信息
        writeClassDesc(desc, false);
        handles.assign(unshared ? null : obj);
        if (desc.isExternalizable() && !desc.isProxy()) {
            writeExternalData((Externalizable) obj);
        } else {
            //把对象转换为二进制
            writeSerialData(obj, desc);
        }
    } finally {
        if (extendedDebugInfo) {
            debugInfoStack.pop();
        }
    }
}

核心步骤

1、把对象转换为二进制

/**
 * Writes instance data for each serializable class of given object, from
 * superclass to subclass.
 */
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;

            if (extendedDebugInfo) {
                debugInfoStack.push(
                    "custom writeObject data (class "" +
                    slotDesc.getName() + "")");
            }
            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);
        }
    }
}

核心步骤

  1. 先写基本数据类型
  2. 再写非基本数据类型
/**
 * Fetches and writes values of serializable fields of given object to
 * stream.  The given class descriptor specifies which field values to
 * write, and in which order they should be written.
 */
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];
    }
    desc.getPrimFieldValues(obj, primVals);
    bout.write(primVals, 0, primDataSize, false);

    //再写非基础数据类型
    ObjectStreamField[] fields = desc.getFields(false); //获取非基础数据类型字段
    Object[] objVals = new Object[desc.getNumObjFields()];
    int numPrimFields = fields.length - objVals.length;
    desc.getObjFieldValues(obj, objVals);
    for (int i = 0; i < objVals.length; i++) { //循环处理非基础数据类型字段
        if (extendedDebugInfo) {
            debugInfoStack.push(
                "field (class "" + desc.getName() + "", name: "" +
                fields[numPrimFields + i].getName() + "", type: "" +
                fields[numPrimFields + i].getType() + "")");
        }
        try {
            writeObject0(objVals[i],
                         fields[numPrimFields + i].isUnshared()); //写非基本数据类型字段
        } finally {
            if (extendedDebugInfo) {
                debugInfoStack.pop();
            }
        }
    }
}

反序列化

ObjectInputStream

读对象,底层是调用readObject0方法。

/**
 * Read an object from the ObjectInputStream.  The class of the object, the
 * signature of the class, and the values of the non-transient and
 * non-static fields of the class and all of its supertypes are read.
 * Default deserializing for a class can be overridden using the writeObject
 * and readObject methods.  Objects referenced by this object are read
 * transitively so that a complete equivalent graph of objects is
 * reconstructed by readObject.
 *
 * <p>The root object is completely restored when all of its fields and the
 * objects it references are completely restored.  At this point the object
 * validation callbacks are executed in order based on their registered
 * priorities. The callbacks are registered by objects (in the readObject
 * special methods) as they are individually restored.
 *
 * <p>Exceptions are thrown for problems with the InputStream and for
 * classes that should not be deserialized.  All exceptions are fatal to
 * the InputStream and leave it in an indeterminate state; it is up to the
 * caller to ignore or recover the stream state.
 *
 * @throws  ClassNotFoundException Class of a serialized object cannot be
 *          found.
 * @throws  InvalidClassException Something is wrong with a class used by
 *          serialization.
 * @throws  StreamCorruptedException Control information in the
 *          stream is inconsistent.
 * @throws  OptionalDataException Primitive data was found in the
 *          stream instead of objects.
 * @throws  IOException Any of the usual Input/Output related exceptions.
 */
public final Object readObject()
    throws IOException, ClassNotFoundException
{
    if (enableOverride) {
        return readObjectOverride();
    }

    // if nested read, passHandle contains handle of enclosing object
    int outerHandle = passHandle;
    try {
        Object obj = readObject0(false); //读对象的底层方法
        handles.markDependency(outerHandle, passHandle);
        ClassNotFoundException ex = handles.lookupException(passHandle);
        if (ex != null) {
            throw ex;
        }
        if (depth == 0) {
            vlist.doCallbacks();
        }
        return obj;
    } finally {
        passHandle = outerHandle;
        if (closed && depth == 0) {
            clear();
        }
    }
}

核心步骤

  1. 校验对象是哪种类型

是字符串?数组?还是普通对象?

  1. 如果是普通对象,就调用readOrdinaryObject方法
/**
 * Underlying readObject implementation.
 */
private Object readObject0(boolean unshared) throws IOException {
    boolean oldMode = bin.getBlockDataMode();
    if (oldMode) {
        int remain = bin.currentBlockRemaining();
        if (remain > 0) {
            throw new OptionalDataException(remain);
        } else if (defaultDataEnd) {
            /*
             * Fix for 4360508: stream is currently at the end of a field
             * value block written via default serialization; since there
             * is no terminating TC_ENDBLOCKDATA tag, simulate
             * end-of-custom-data behavior explicitly.
             */
            throw new OptionalDataException(true);
        }
        bin.setBlockDataMode(false);
    }

    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);
    }
}

核心步骤

  1. 读对象的各个字段
  2. 创建对象
/**
 * Reads and returns "ordinary" (i.e., not a String, Class,
 * ObjectStreamClass, array, or enum constant) object, or null if object's
 * class is unresolvable (in which case a ClassNotFoundException will be
 * associated with object's handle).  Sets passHandle to object's assigned
 * handle.
 */
private Object readOrdinaryObject(boolean unshared)
    throws IOException
{
    if (bin.readByte() != TC_OBJECT) {
        throw new InternalError();
    }
    
//读对象的各个字段
    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");
    }

    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()) {
        readExternalData((Externalizable) obj, desc);
    } else {
        readSerialData(obj, desc);
    }

    handles.finish(passHandle);

    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;
}

ObjectStreamClass

核心步骤

  1. 创建对象
/**
 * Creates a new instance of the represented class.  If the class is
 * externalizable, invokes its public no-arg constructor; otherwise, if the
 * class is serializable, invokes the no-arg constructor of the first
 * non-serializable superclass.  Throws UnsupportedOperationException if
 * this class descriptor is not associated with a class, if the associated
 * class is non-serializable or if the appropriate no-arg constructor is
 * inaccessible/unavailable.
 */
Object newInstance()
    throws InstantiationException, InvocationTargetException,
           UnsupportedOperationException
{
    requireInitialized();
    if (cons != null) {
        try {
            if (domains == null || domains.length == 0) {
                return cons.newInstance(); //创建对象
            } else {
                JavaSecurityAccess jsa = SharedSecrets.getJavaSecurityAccess();
                PrivilegedAction<?> pea = () -> {
                    try {
                        return cons.newInstance();
                    } catch (InstantiationException
                             | InvocationTargetException
                             | IllegalAccessException x) {
                        throw new UndeclaredThrowableException(x);
                    }
                }; // Can't use PrivilegedExceptionAction with jsa
                try {
                    return jsa.doIntersectionPrivilege(pea,
                               AccessController.getContext(),
                               new AccessControlContext(domains));
                } catch (UndeclaredThrowableException x) {
                    Throwable cause = x.getCause();
                    if (cause instanceof InstantiationException)
                        throw (InstantiationException) cause;
                    if (cause instanceof InvocationTargetException)
                        throw (InvocationTargetException) cause;
                    if (cause instanceof IllegalAccessException)
                        throw (IllegalAccessException) cause;
                    // not supposed to happen
                    throw x;
                }
            }
        } catch (IllegalAccessException ex) {
            // should not occur, as access checks have been suppressed
            throw new InternalError(ex);
        }
    } else {
        throw new UnsupportedOperationException();
    }
}

底层其实就是调用构造器的newInstance方法创建对象,最底层其实就是调用native方法:

NativeConstructorAccessorImpl类

private static native Object newInstance0(Constructor<?> var0, Object[] var1) throws InstantiationException, IllegalArgumentException, InvocationTargetException;

参考

developer.aliyun.com/article/643…

zhzhdoai.github.io/2020/02/07/…