objectoutputstream.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,976 行 · 第 1/5 页

JAVA
1,976
字号
    private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared) 	throws IOException     {	bout.writeByte(TC_CLASSDESC);	handles.assign(unshared ? null : desc);		if (protocol == PROTOCOL_VERSION_1) {	    // do not invoke class descriptor write hook with old protocol	    desc.writeNonProxy(this);	} else {	    writeClassDescriptor(desc);	}		Class cl = desc.forClass();	bout.setBlockDataMode(true);	annotateClass(cl);	bout.setBlockDataMode(false);	bout.writeByte(TC_ENDBLOCKDATA);		writeClassDesc(desc.getSuperDesc(), false);    }        /**     * Writes given string to stream, using standard or long UTF format     * depending on string length.     */    private void writeString(String str, boolean unshared) throws IOException {	handles.assign(unshared ? null : str);	long utflen = bout.getUTFLength(str);	if (utflen <= 0xFFFF) {	    bout.writeByte(TC_STRING);	    bout.writeUTF(str, utflen);	} else {	    bout.writeByte(TC_LONGSTRING);	    bout.writeLongUTF(str, utflen);	}    }        /**     * Writes given array object to stream.     */    private void writeArray(Object array, 			    ObjectStreamClass desc, 			    boolean unshared) 	throws IOException     {	bout.writeByte(TC_ARRAY);	writeClassDesc(desc, false);	handles.assign(unshared ? null : array);		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);	    for (int i = 0; i < len; i++) {		writeObject0(objs[i], false);	    }	}    }        /**     * Writes representation of a "ordinary" (i.e., not a String, Class,     * ObjectStreamClass or array) serializable object to the stream.     */    private void writeOrdinaryObject(Object obj, 				     ObjectStreamClass desc, 				     boolean unshared) 	throws IOException     {	bout.writeByte(TC_OBJECT);	writeClassDesc(desc, false);	handles.assign(unshared ? null : obj);	if (desc.isExternalizable() && !desc.isProxy()) {	    writeExternalData((Externalizable) obj);	} else {	    writeSerialData(obj, desc);	}    }        /**     * Writes externalizable data of given object by invoking its     * writeExternal() method.     */    private void writeExternalData(Externalizable obj) throws IOException {	Object oldObj = curObj;	ObjectStreamClass oldDesc = curDesc;	PutFieldImpl oldPut = curPut;	curObj = obj;	curDesc = null;	curPut = null;		if (protocol == PROTOCOL_VERSION_1) {	    obj.writeExternal(this);	} else {	    bout.setBlockDataMode(true);	    obj.writeExternal(this);	    bout.setBlockDataMode(false);	    bout.writeByte(TC_ENDBLOCKDATA);	}	curObj = oldObj;	curDesc = oldDesc;	curPut = oldPut;    }        /**     * 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()) {		Object oldObj = curObj;		ObjectStreamClass oldDesc = curDesc;		PutFieldImpl oldPut = curPut;		curObj = obj;		curDesc = slotDesc;		curPut = null;		bout.setBlockDataMode(true);		slotDesc.invokeWriteObject(obj, this);		bout.setBlockDataMode(false);		bout.writeByte(TC_ENDBLOCKDATA);		curObj = oldObj;		curDesc = oldDesc;		curPut = oldPut;	    } else {		defaultWriteFields(obj, slotDesc);	    }	}    }        /**     * 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    {	// TODO: perform conservative isInstance check here?	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++) {	    writeObject0(objVals[i], fields[numPrimFields + i].isUnshared());	}    }    /**     * Attempts to write to stream fatal IOException that has caused     * serialization to abort.     */    private void writeFatalException(IOException ex) throws IOException {	/*	 * Note: the serialization specification states that if a second	 * IOException occurs while attempting to serialize the original fatal	 * exception to the stream, then a StreamCorruptedException should be	 * thrown (section 2.1).  However, due to a bug in previous	 * implementations of serialization, StreamCorruptedExceptions were	 * rarely (if ever) actually thrown--the "root" exceptions from	 * underlying streams were thrown instead.  This historical behavior is	 * followed here for consistency.	 */	clear();	boolean oldMode = bout.setBlockDataMode(false);	try {	    bout.writeByte(TC_EXCEPTION);	    writeObject0(ex, false);	    clear();	} finally {	    bout.setBlockDataMode(oldMode);	}    }    /**     * Converts specified span of float values into byte values.     */    // TODO: remove once hotspot inlines Float.floatToIntBits    private static native void floatsToBytes(float[] src, int srcpos, 					     byte[] dst, int dstpos, 					     int nfloats);    /**     * Converts specified span of double values into byte values.     */    // TODO: remove once hotspot inlines Double.doubleToLongBits    private static native void doublesToBytes(double[] src, int srcpos,					      byte[] dst, int dstpos, 					      int ndoubles);    /**     * Default PutField implementation.     */    private class PutFieldImpl extends PutField {	/** class descriptor describing serializable fields */	private final ObjectStreamClass desc;	/** primitive field values */	private final byte[] primVals;	/** object field values */	private final Object[] objVals;	/**	 * Creates PutFieldImpl object for writing fields defined in given	 * class descriptor.	 */	PutFieldImpl(ObjectStreamClass desc) {	    this.desc = desc;	    primVals = new byte[desc.getPrimDataSize()];	    objVals = new Object[desc.getNumObjFields()];	}	public void put(String name, boolean val) {	    Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);	}	public void put(String name, byte val) {	    primVals[getFieldOffset(name, Byte.TYPE)] = val;	}	public void put(String name, char val) {	    Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val);	}	public void put(String name, short val) {	    Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val);	}	public void put(String name, int val) {	    Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val);	}	public void put(String name, float val) {	    Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val);	}	public void put(String name, long val) {	    Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val);	}	public void put(String name, double val) {	    Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val);	}	public void put(String name, Object val) {	    objVals[getFieldOffset(name, Object.class)] = val;	}	// deprecated in ObjectOutputStream.PutField	public void write(ObjectOutput out) throws IOException {	    /*	     * Applications should *not* use this method to write PutField	     * data, as it will lead to stream corruption if the PutField	     * object writes any primitive data (since block data mode is not	     * unset/set properly, as is done in OOS.writeFields()).  This	     * broken implementation is being retained solely for behavioral	     * compatibility, in order to support applications which use	     * OOS.PutField.write() for writing only non-primitive data.	     * 	     * Serialization of unshared objects is not implemented here since	     * it is not necessary for backwards compatibility; also, unshared	     * semantics may not be supported by the given ObjectOutput	     * instance.  Applications which write unshared objects using the	     * PutField API must use OOS.writeFields().	     */	    out.write(primVals, 0, primVals.length);	    	    ObjectStreamField[] fields = desc.getFields(false);	    int numPrimFields = fields.length - objVals.length;	    // TODO: warn if numPrimFields > 0?	    for (int i = 0; i < objVals.length; i++) {		if (fields[numPrimFields + i].isUnshared()) {		    throw new IOException("cannot write unshared object");		}		out.writeObject(objVals[i]);	    }	}		/**	 * Writes buffered primitive data and object fields to stream.	 */	void writeFields() throws IOException {	    bout.write(primVals, 0, primVals.length, false);	    ObjectStreamField[] fields = desc.getFields(false);	    int numPrimFields = fields.length - objVals.length;	    for (int i = 0; i < objVals.length; i++) {		writeObject0(		    objVals[i], fields[numPrimFields + i].isUnshared());	    }	}		/**	 * Returns offset of field with given name and type.  A specified type	 * of null matches all types, Object.class matches all non-primitive	 * types, and any other non-null type matches assignable types only.	 * Throws IllegalArgumentException if no matching field found.	 */	private int getFieldOffset(String name, Class type) {	    ObjectStreamField field = desc.getField(name, type);	    if (field == null) {		throw new IllegalArgumentException("no such field");	    }	    return field.getOffset();	}    }    /**     * Buffered output stream with two modes: in default mode, outputs data in     * same format as DataOutputStream; in "block data" mode, outputs data     * bracketed by block data markers (see object serialization specification     * for details).     */    private static class BlockDataOutputStream 	extends OutputStream implements DataOutput    {	/** maximum data block length */	private static final int MAX_BLOCK_SIZE = 1024;	/** maximum data block header length */	private static final int MAX_HEADER_SIZE = 5;	/** (tunable) length of char buffer (for writing strings) */	private static final int CHAR_BUF_SIZE = 256;	/** buffer for writing general/block data */	private final byte[] buf = new byte[MAX_BLOCK_SIZE];	/** buffer for writing block data headers */	private final byte[] hbuf = new byte[MAX_HEADER_SIZE];	/** char buffer for fast string writes */	private final char[] cbuf = new char[CHAR_BUF_SIZE];		/** block data mode */	private boolean blkmode = false;	/** current offset into buf */	private int pos = 0;	/** underlying output stream */	private final OutputStream out;	/** loopback stream (for data writes that span data blocks) */	private final DataOutputStream dout;	/**	 * Creates new BlockDataOutputStream on top of given underlying stream.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?