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 + -
显示快捷键?