private int writeObjectInternal(Object object, boolean unshared,
            boolean computeClassBasedReplacement,
            boolean computeStreamReplacement) throws IOException {

        if (object == null) {
            writeNull();
            return -1;
        }
        if (!unshared) {
            int handle = dumpCycle(object);
            if (handle != -1) {
                return handle; // cyclic reference
            }
        }

        // Non-null object, first time seen...
        Class<?> objClass = object.getClass();
        ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(objClass);

        nestedLevels++;
        try {

            if (!(enableReplace && computeStreamReplacement)) {
                // Is it a Class ?
                if (objClass == ObjectStreamClass.CLASSCLASS) {
                    return writeNewClass((Class<?>) object, unshared);
                }
                // Is it an ObjectStreamClass ?
                if (objClass == ObjectStreamClass.OBJECTSTREAMCLASSCLASS) {
                    return writeClassDesc((ObjectStreamClass) object, unshared);
                }
            }

            if (clDesc.isSerializable() && computeClassBasedReplacement) {
                if (clDesc.hasMethodWriteReplace()){
                    Method methodWriteReplace = clDesc.getMethodWriteReplace();
                    Object replObj;
                    try {
                        replObj = methodWriteReplace.invoke(object, (Object[]) null);
                    } catch (IllegalAccessException iae) {
                        replObj = object;
                    } catch (InvocationTargetException ite) {
                        // WARNING - Not sure this is the right thing to do
                        // if we can't run the method
                        Throwable target = ite.getTargetException();
                        if (target instanceof ObjectStreamException) {
                            throw (ObjectStreamException) target;
                        } else if (target instanceof Error) {
                            throw (Error) target;
                        } else {
                            throw (RuntimeException) target;
                        }
                    }
                    if (replObj != object) {
                        // All over, class-based replacement off this time.
                        int replacementHandle = writeObjectInternal(replObj, false, false,
                                computeStreamReplacement);
                        // Make the original object also map to the same
                        // handle.
                        if (replacementHandle != -1) {
                            objectsWritten.put(object, replacementHandle);
                        }
                        return replacementHandle;
                    }
                }

            }

            // We get here either if class-based replacement was not needed or
            // if it was needed but produced the same object or if it could not
            // be computed.
            if (enableReplace && computeStreamReplacement) {
                // Now we compute the stream-defined replacement.
                Object streamReplacement = replaceObject(object);
                if (streamReplacement != object) {
                    // All over, class-based replacement off this time.
                    int replacementHandle = writeObjectInternal(streamReplacement, false,
                            computeClassBasedReplacement, false);
                    // Make the original object also map to the same handle.
                    if (replacementHandle != -1) {
                        objectsWritten.put(object, replacementHandle);
                    }
                    return replacementHandle;
                }
            }

            // We get here if stream-based replacement produced the same object

            // Is it a Class ?
            if (objClass == ObjectStreamClass.CLASSCLASS) {
                return writeNewClass((Class<?>) object, unshared);
            }

            // Is it an ObjectStreamClass ?
            if (objClass == ObjectStreamClass.OBJECTSTREAMCLASSCLASS) {
                return writeClassDesc((ObjectStreamClass) object, unshared);
            }

            // Is it a String ? (instanceof, but == is faster)
            if (objClass == ObjectStreamClass.STRINGCLASS) {
                return writeNewString((String) object, unshared);
            }

            // Is it an Array ?
            if (objClass.isArray()) {
                return writeNewArray(object, objClass, clDesc, objClass
                        .getComponentType(), unshared);
            }

            if (object instanceof Enum) {
                return writeNewEnum(object, objClass, unshared);
            }

            // Not a String or Class or Array. Default procedure.
            return writeNewObject(object, objClass, clDesc, unshared);
        } finally {
            nestedLevels--;
        }
    }
private int writeObjectInternal ( Object object , boolean unshared , boolean computeClassBasedReplacement , boolean computeStreamReplacement ) throws IOException { if ( object == null ) { writeNull ( ) ; return - 1 ; } if ( ! unshared ) { int handle = dumpCycle ( object ) ; if ( handle != - 1 ) { return handle ; } } Class < ? > objClass = object . getClass ( ) ; ObjectStreamClass clDesc = ObjectStreamClass . lookupStreamClass ( objClass ) ; nestedLevels ++ ; try { if ( ! ( enableReplace && computeStreamReplacement ) ) { if ( objClass == ObjectStreamClass . CLASSCLASS ) { return writeNewClass ( ( Class < ? > ) object , unshared ) ; } if ( objClass == ObjectStreamClass . OBJECTSTREAMCLASSCLASS ) { return writeClassDesc ( ( ObjectStreamClass ) object , unshared ) ; } } if ( clDesc . isSerializable ( ) && computeClassBasedReplacement ) { if ( clDesc . hasMethodWriteReplace ( ) ) { Method methodWriteReplace = clDesc . getMethodWriteReplace ( ) ; Object replObj ; try { replObj = methodWriteReplace . invoke ( object , ( Object [ ] ) null ) ; } catch ( IllegalAccessException iae ) { replObj = object ; } catch ( InvocationTargetException ite ) { Throwable target = ite . getTargetException ( ) ; if ( target instanceof ObjectStreamException ) { throw ( ObjectStreamException ) target ; } else if ( target instanceof Error ) { throw ( Error ) target ; } else { throw ( RuntimeException ) target ; } } if ( replObj != object ) { int replacementHandle = writeObjectInternal ( replObj , false , false , computeStreamReplacement ) ; if ( replacementHandle != - 1 ) { objectsWritten . put ( object , replacementHandle ) ; } return replacementHandle ; } } } if ( enableReplace && computeStreamReplacement ) { Object streamReplacement = replaceObject ( object ) ; if ( streamReplacement != object ) { int replacementHandle = writeObjectInternal ( streamReplacement , false , computeClassBasedReplacement , false ) ; if ( replacementHandle != - 1 ) { objectsWritten . put ( object , replacementHandle ) ; } return replacementHandle ; } } if ( objClass == ObjectStreamClass . CLASSCLASS ) { return writeNewClass ( ( Class < ? > ) object , unshared ) ; } if ( objClass == ObjectStreamClass . OBJECTSTREAMCLASSCLASS ) { return writeClassDesc ( ( ObjectStreamClass ) object , unshared ) ; } if ( objClass == ObjectStreamClass . STRINGCLASS ) { return writeNewString ( ( String ) object , unshared ) ; } if ( objClass . isArray ( ) ) { return writeNewArray ( object , objClass , clDesc , objClass . getComponentType ( ) , unshared ) ; } if ( object instanceof Enum ) { return writeNewEnum ( object , objClass , unshared ) ; } return writeNewObject ( object , objClass , clDesc , unshared ) ; } finally { nestedLevels -- ; } }
Write object {@code object} into the receiver's underlying stream.

@param object
The object to write
@param unshared
Write the object unshared
@param computeClassBasedReplacement
A boolean indicating if class-based replacement should be
computed (if supported) for the object.
@param computeStreamReplacement
A boolean indicating if stream-based replacement should be
computed (if supported) for the object.
@return the handle assigned to the final object being dumped

@throws IOException
If an IO exception happened when writing the object

@see ObjectInputStream#readObject()