Program: 43010
Project: 43010
Buggy source:
protected void doWriteObject(final Object original,final boolean unshared) throws IOException {
  final ClassExternalizerFactory classExternalizerFactory=this.classExternalizerFactory;
  final ObjectResolver objectResolver=this.objectResolver;
  Object obj=original;
  Class<?> objClass;
  int id;
  boolean isArray, isEnum;
  SerializableClass info;
  boolean unreplaced=true;
  final int configuredVersion=this.configuredVersion;
  try {
    for (; ; ) {
      if (obj == null) {
        write(ID_NULL);
        return;
      }
      final int rid;
      if (!unshared && (rid=instanceCache.get(obj,-1)) != -1) {
        if (configuredVersion >= 2) {
          final int diff=rid - instanceSeq;
          if (diff >= -256) {
            write(ID_REPEAT_OBJECT_NEAR);
            write(diff);
          }
 else           if (diff >= -65536) {
            write(ID_REPEAT_OBJECT_NEARISH);
            writeShort(diff);
          }
          return;
        }
        write(ID_REPEAT_OBJECT_FAR);
        writeInt(rid);
        return;
      }
      final ObjectTable.Writer objectTableWriter;
      if (!unshared && (objectTableWriter=objectTable.getObjectWriter(obj)) != null) {
        write(ID_PREDEFINED_OBJECT);
        if (configuredVersion == 1) {
          objectTableWriter.writeObject(getBlockMarshaller(),obj);
          writeEndBlock();
        }
 else {
          objectTableWriter.writeObject(this,obj);
        }
        return;
      }
      objClass=obj.getClass();
      id=(configuredVersion >= 2 ? BASIC_CLASSES_V2 : BASIC_CLASSES).get(objClass,-1);
      if (id == ID_CLASS_CLASS) {
        final Class<?> classObj=(Class<?>)obj;
        if (configuredVersion >= 2) {
          final int cid=(configuredVersion >= 2 ? BASIC_CLASSES_V2 : BASIC_CLASSES).get(classObj,-1);
switch (cid) {
case -1:
case ID_SINGLETON_MAP_OBJECT:
case ID_SINGLETON_SET_OBJECT:
case ID_SINGLETON_LIST_OBJECT:
case ID_EMPTY_MAP_OBJECT:
case ID_EMPTY_SET_OBJECT:
case ID_EMPTY_LIST_OBJECT:
{
              break;
            }
default :
{
            write(cid);
            return;
          }
      }
    }
    write(ID_NEW_OBJECT);
    write(ID_CLASS_CLASS);
    writeClassClass(classObj);
    instanceCache.put(classObj,instanceSeq++);
    return;
  }
  isEnum=obj instanceof Enum;
  isArray=objClass.isArray();
  info=isArray || isEnum || id != -1 ? null : registry.lookup(objClass);
  if (unreplaced) {
    if (info != null) {
      if (info.hasWriteReplace()) {
        obj=info.callWriteReplace(obj);
      }
    }
    obj=objectResolver.writeReplace(obj);
    if (obj != original) {
      unreplaced=false;
      continue;
    }
 else {
      break;
    }
  }
 else {
    break;
  }
}
if (isEnum) {
  final Enum<?> theEnum=(Enum<?>)obj;
  write(ID_NEW_OBJECT);
  writeEnumClass(theEnum.getDeclaringClass());
  writeString(theEnum.name());
  instanceCache.put(obj,instanceSeq++);
  return;
}
switch (id) {
case ID_BYTE_CLASS:
{
    if (configuredVersion >= 2) {
      write(ID_BYTE_OBJECT);
      writeByte(((Byte)obj).byteValue());
    }
 else {
      write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
      write(ID_BYTE_CLASS);
      writeByte(((Byte)obj).byteValue());
    }
    return;
  }
case ID_BOOLEAN_CLASS:
{
  if (configuredVersion >= 2) {
    write(((Boolean)obj).booleanValue() ? ID_BOOLEAN_OBJECT_TRUE : ID_BOOLEAN_OBJECT_FALSE);
  }
 else {
    write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
    write(ID_BOOLEAN_CLASS);
    writeBoolean(((Boolean)obj).booleanValue());
  }
  return;
}
case ID_CHARACTER_CLASS:
{
if (configuredVersion >= 2) {
  write(ID_CHARACTER_OBJECT);
  writeChar(((Character)obj).charValue());
}
 else {
  write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
  write(ID_CHARACTER_CLASS);
  writeChar(((Character)obj).charValue());
}
return;
}
case ID_DOUBLE_CLASS:
{
if (configuredVersion >= 2) {
write(ID_DOUBLE_OBJECT);
writeDouble(((Double)obj).doubleValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_DOUBLE_CLASS);
writeDouble(((Double)obj).doubleValue());
}
return;
}
case ID_FLOAT_CLASS:
{
if (configuredVersion >= 2) {
write(ID_FLOAT_OBJECT);
writeFloat(((Float)obj).floatValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_FLOAT_CLASS);
writeFloat(((Float)obj).floatValue());
}
return;
}
case ID_INTEGER_CLASS:
{
if (configuredVersion >= 2) {
write(ID_INTEGER_OBJECT);
writeInt(((Integer)obj).intValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_INTEGER_CLASS);
writeInt(((Integer)obj).intValue());
}
return;
}
case ID_LONG_CLASS:
{
if (configuredVersion >= 2) {
write(ID_LONG_OBJECT);
writeLong(((Long)obj).longValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_LONG_CLASS);
writeLong(((Long)obj).longValue());
}
return;
}
case ID_SHORT_CLASS:
{
if (configuredVersion >= 2) {
write(ID_SHORT_OBJECT);
writeShort(((Short)obj).shortValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_SHORT_CLASS);
writeShort(((Short)obj).shortValue());
}
return;
}
case ID_STRING_CLASS:
{
final String string=(String)obj;
if (configuredVersion >= 2) {
final int len=string.length();
if (len == 0) {
write(ID_STRING_EMPTY);
return;
}
 else if (len <= 256) {
write(ID_STRING_SMALL);
write(len);
}
 else if (len <= 65336) {
write(ID_STRING_MEDIUM);
writeShort(len);
}
 else {
write(ID_STRING_LARGE);
writeInt(len);
}
flush();
UTFUtils.writeUTFBytes(byteOutput,string);
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_STRING_CLASS);
writeString(string);
}
if (unshared) {
instanceCache.put(obj,-1);
instanceSeq++;
}
 else {
instanceCache.put(obj,instanceSeq++);
}
return;
}
case ID_BYTE_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final byte[] bytes=(byte[])obj;
final int len=bytes.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_BYTE);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_BYTE);
write(bytes,0,len);
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_BYTE);
write(bytes,0,len);
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_BYTE);
write(bytes,0,len);
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_BYTE_ARRAY_CLASS);
writeInt(len);
write(bytes,0,len);
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_BOOLEAN_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final boolean[] booleans=(boolean[])obj;
final int len=booleans.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_BOOLEAN);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_BOOLEAN);
writeBooleanArray(booleans);
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_BOOLEAN);
writeBooleanArray(booleans);
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_BOOLEAN);
writeBooleanArray(booleans);
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_BOOLEAN_ARRAY_CLASS);
writeInt(len);
writeBooleanArray(booleans);
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CHAR_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final char[] chars=(char[])obj;
final int len=chars.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_CHAR);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_CHAR);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_CHAR);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_CHAR);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_CHAR_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_SHORT_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final short[] shorts=(short[])obj;
final int len=shorts.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_SHORT);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_SHORT);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_SHORT);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_SHORT);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_SHORT_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_INT_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final int[] ints=(int[])obj;
final int len=ints.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_INT);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_INT);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_INT);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_INT);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_INT_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_LONG_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final long[] longs=(long[])obj;
final int len=longs.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_LONG);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_LONG);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_LONG);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_LONG);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_LONG_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_FLOAT_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final float[] floats=(float[])obj;
final int len=floats.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_FLOAT);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_FLOAT);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_FLOAT);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_FLOAT);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_FLOAT_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_DOUBLE_ARRAY_CLASS:
{
instanceCache.put(obj,instanceSeq++);
final double[] doubles=(double[])obj;
final int len=doubles.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_DOUBLE);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_DOUBLE);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_DOUBLE);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_DOUBLE);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_DOUBLE_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CC_HASH_SET:
case ID_CC_LINKED_HASH_SET:
case ID_CC_TREE_SET:
case ID_CC_ARRAY_LIST:
case ID_CC_LINKED_LIST:
{
instanceCache.put(obj,instanceSeq++);
final Collection<?> collection=(Collection<?>)obj;
final int len=collection.size();
if (len == 0) {
write(unshared ? ID_COLLECTION_EMPTY_UNSHARED : ID_COLLECTION_EMPTY);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
for (Object o : collection) {
doWriteObject(o,false);
}
}
 else if (len <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(len);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
for (Object o : collection) {
doWriteObject(o,false);
}
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(len);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
for (Object o : collection) {
doWriteObject(o,false);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CC_HASH_MAP:
case ID_CC_HASHTABLE:
case ID_CC_IDENTITY_HASH_MAP:
case ID_CC_LINKED_HASH_MAP:
case ID_CC_TREE_MAP:
{
instanceCache.put(obj,instanceSeq++);
final Map<?,?> map=(Map<?,?>)obj;
final int len=map.size();
if (len == 0) {
write(unshared ? ID_COLLECTION_EMPTY_UNSHARED : ID_COLLECTION_EMPTY);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
for (Map.Entry<?,?> entry : map.entrySet()) {
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
}
}
 else if (len <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(len);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
for (Map.Entry<?,?> entry : map.entrySet()) {
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
}
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(len);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
for (Map.Entry<?,?> entry : map.entrySet()) {
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_EMPTY_MAP_OBJECT:
case ID_EMPTY_SET_OBJECT:
case ID_EMPTY_LIST_OBJECT:
{
write(id);
return;
}
case ID_SINGLETON_MAP_OBJECT:
{
instanceCache.put(obj,instanceSeq++);
write(id);
final Map.Entry entry=(Map.Entry)((Map)obj).entrySet().iterator().next();
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_SINGLETON_LIST_OBJECT:
case ID_SINGLETON_SET_OBJECT:
{
instanceCache.put(obj,instanceSeq++);
write(id);
doWriteObject(((Collection)obj).iterator().next(),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case -1:
break;
default :
throw new NotSerializableException(objClass.getName());
}
if (isArray) {
instanceCache.put(obj,instanceSeq++);
final Object[] objects=(Object[])obj;
final int len=objects.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
writeClass(objClass.getComponentType());
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
writeClass(objClass.getComponentType());
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
writeClass(objClass.getComponentType());
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
writeClass(objClass.getComponentType());
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
writeObjectArrayClass(objClass);
writeInt(len);
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (Proxy.isProxyClass(objClass)) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
instanceCache.put(obj,instanceSeq++);
writeProxyClass(objClass);
doWriteObject(Proxy.getInvocationHandler(obj),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
Externalizer externalizer;
if (externalizers.containsKey(objClass)) {
externalizer=externalizers.get(objClass);
}
 else {
externalizer=classExternalizerFactory.getExternalizer(objClass);
externalizers.put(objClass,externalizer);
}
if (externalizer != null) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
writeExternalizerClass(objClass,externalizer);
instanceCache.put(obj,instanceSeq++);
final ObjectOutput objectOutput;
objectOutput=getObjectOutput();
externalizer.writeExternal(obj,objectOutput);
writeEndBlock();
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (obj instanceof Externalizable) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
instanceCache.put(obj,instanceSeq++);
final Externalizable ext=(Externalizable)obj;
final ObjectOutput objectOutput=getObjectOutput();
writeExternalizableClass(objClass);
ext.writeExternal(objectOutput);
writeEndBlock();
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (obj instanceof Serializable) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
writeSerializableClass(objClass);
instanceCache.put(obj,instanceSeq++);
doWriteSerializableObject(info,obj,objClass);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
throw new NotSerializableException(objClass.getName());
}
  finally {
if (!unreplaced && obj != original) {
final int replId=instanceCache.get(obj,-1);
if (replId != -1) {
instanceCache.put(original,replId);
}
}
}
}

Fixed version (ground truth):
protected void doWriteObject(final Object original,final boolean unshared) throws IOException {
  final ClassExternalizerFactory classExternalizerFactory=this.classExternalizerFactory;
  final ObjectResolver objectResolver=this.objectResolver;
  Object obj=original;
  Class<?> objClass;
  int id;
  boolean isArray, isEnum;
  SerializableClass info;
  boolean unreplaced=true;
  final int configuredVersion=this.configuredVersion;
  try {
    for (; ; ) {
      if (obj == null) {
        write(ID_NULL);
        return;
      }
      final int rid;
      if (!unshared && (rid=instanceCache.get(obj,-1)) != -1) {
        if (configuredVersion >= 2) {
          final int diff=rid - instanceSeq;
          if (diff >= -256) {
            write(ID_REPEAT_OBJECT_NEAR);
            write(diff);
          }
 else           if (diff >= -65536) {
            write(ID_REPEAT_OBJECT_NEARISH);
            writeShort(diff);
          }
          return;
        }
        write(ID_REPEAT_OBJECT_FAR);
        writeInt(rid);
        return;
      }
      final ObjectTable.Writer objectTableWriter;
      if (!unshared && (objectTableWriter=objectTable.getObjectWriter(obj)) != null) {
        write(ID_PREDEFINED_OBJECT);
        if (configuredVersion == 1) {
          objectTableWriter.writeObject(getBlockMarshaller(),obj);
          writeEndBlock();
        }
 else {
          objectTableWriter.writeObject(this,obj);
        }
        return;
      }
      objClass=obj.getClass();
      id=(configuredVersion >= 2 ? BASIC_CLASSES_V2 : BASIC_CLASSES).get(objClass,-1);
      if (id == ID_CLASS_CLASS) {
        final Class<?> classObj=(Class<?>)obj;
        if (configuredVersion >= 2) {
          final int cid=BASIC_CLASSES_V2.get(classObj,-1);
switch (cid) {
case -1:
case ID_SINGLETON_MAP_OBJECT:
case ID_SINGLETON_SET_OBJECT:
case ID_SINGLETON_LIST_OBJECT:
case ID_EMPTY_MAP_OBJECT:
case ID_EMPTY_SET_OBJECT:
case ID_EMPTY_LIST_OBJECT:
{
              break;
            }
default :
{
            write(cid);
            return;
          }
      }
    }
    write(ID_NEW_OBJECT);
    writeClassClass(classObj);
    instanceCache.put(classObj,instanceSeq++);
    return;
  }
  isEnum=obj instanceof Enum;
  isArray=objClass.isArray();
  info=isArray || isEnum || id != -1 ? null : registry.lookup(objClass);
  if (unreplaced) {
    if (info != null) {
      if (info.hasWriteReplace()) {
        obj=info.callWriteReplace(obj);
      }
    }
    obj=objectResolver.writeReplace(obj);
    if (obj != original) {
      unreplaced=false;
      continue;
    }
 else {
      break;
    }
  }
 else {
    break;
  }
}
if (isEnum) {
  final Enum<?> theEnum=(Enum<?>)obj;
  write(ID_NEW_OBJECT);
  writeEnumClass(theEnum.getDeclaringClass());
  writeString(theEnum.name());
  instanceCache.put(obj,instanceSeq++);
  return;
}
switch (id) {
case ID_BYTE_CLASS:
{
    if (configuredVersion >= 2) {
      write(ID_BYTE_OBJECT);
      writeByte(((Byte)obj).byteValue());
    }
 else {
      write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
      write(ID_BYTE_CLASS);
      writeByte(((Byte)obj).byteValue());
    }
    return;
  }
case ID_BOOLEAN_CLASS:
{
  if (configuredVersion >= 2) {
    write(((Boolean)obj).booleanValue() ? ID_BOOLEAN_OBJECT_TRUE : ID_BOOLEAN_OBJECT_FALSE);
  }
 else {
    write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
    write(ID_BOOLEAN_CLASS);
    writeBoolean(((Boolean)obj).booleanValue());
  }
  return;
}
case ID_CHARACTER_CLASS:
{
if (configuredVersion >= 2) {
  write(ID_CHARACTER_OBJECT);
  writeChar(((Character)obj).charValue());
}
 else {
  write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
  write(ID_CHARACTER_CLASS);
  writeChar(((Character)obj).charValue());
}
return;
}
case ID_DOUBLE_CLASS:
{
if (configuredVersion >= 2) {
write(ID_DOUBLE_OBJECT);
writeDouble(((Double)obj).doubleValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_DOUBLE_CLASS);
writeDouble(((Double)obj).doubleValue());
}
return;
}
case ID_FLOAT_CLASS:
{
if (configuredVersion >= 2) {
write(ID_FLOAT_OBJECT);
writeFloat(((Float)obj).floatValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_FLOAT_CLASS);
writeFloat(((Float)obj).floatValue());
}
return;
}
case ID_INTEGER_CLASS:
{
if (configuredVersion >= 2) {
write(ID_INTEGER_OBJECT);
writeInt(((Integer)obj).intValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_INTEGER_CLASS);
writeInt(((Integer)obj).intValue());
}
return;
}
case ID_LONG_CLASS:
{
if (configuredVersion >= 2) {
write(ID_LONG_OBJECT);
writeLong(((Long)obj).longValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_LONG_CLASS);
writeLong(((Long)obj).longValue());
}
return;
}
case ID_SHORT_CLASS:
{
if (configuredVersion >= 2) {
write(ID_SHORT_OBJECT);
writeShort(((Short)obj).shortValue());
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_SHORT_CLASS);
writeShort(((Short)obj).shortValue());
}
return;
}
case ID_STRING_CLASS:
{
final String string=(String)obj;
if (configuredVersion >= 2) {
final int len=string.length();
if (len == 0) {
write(ID_STRING_EMPTY);
return;
}
 else if (len <= 256) {
write(ID_STRING_SMALL);
write(len);
}
 else if (len <= 65336) {
write(ID_STRING_MEDIUM);
writeShort(len);
}
 else {
write(ID_STRING_LARGE);
writeInt(len);
}
flush();
UTFUtils.writeUTFBytes(byteOutput,string);
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_STRING_CLASS);
writeString(string);
}
if (unshared) {
instanceCache.put(obj,-1);
instanceSeq++;
}
 else {
instanceCache.put(obj,instanceSeq++);
}
return;
}
case ID_BYTE_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final byte[] bytes=(byte[])obj;
final int len=bytes.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_BYTE);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_BYTE);
write(bytes,0,len);
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_BYTE);
write(bytes,0,len);
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_BYTE);
write(bytes,0,len);
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_BYTE_ARRAY_CLASS);
writeInt(len);
write(bytes,0,len);
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_BOOLEAN_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final boolean[] booleans=(boolean[])obj;
final int len=booleans.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_BOOLEAN);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_BOOLEAN);
writeBooleanArray(booleans);
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_BOOLEAN);
writeBooleanArray(booleans);
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_BOOLEAN);
writeBooleanArray(booleans);
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_BOOLEAN_ARRAY_CLASS);
writeInt(len);
writeBooleanArray(booleans);
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CHAR_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final char[] chars=(char[])obj;
final int len=chars.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_CHAR);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_CHAR);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_CHAR);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_CHAR);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_CHAR_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeChar(chars[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_SHORT_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final short[] shorts=(short[])obj;
final int len=shorts.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_SHORT);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_SHORT);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_SHORT);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_SHORT);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_SHORT_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeShort(shorts[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_INT_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final int[] ints=(int[])obj;
final int len=ints.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_INT);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_INT);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_INT);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_INT);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_INT_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeInt(ints[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_LONG_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final long[] longs=(long[])obj;
final int len=longs.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_LONG);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_LONG);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_LONG);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_LONG);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_LONG_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeLong(longs[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_FLOAT_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final float[] floats=(float[])obj;
final int len=floats.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_FLOAT);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_FLOAT);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_FLOAT);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_FLOAT);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_FLOAT_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeFloat(floats[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_DOUBLE_ARRAY_CLASS:
{
instanceCache.put(obj,instanceSeq++);
final double[] doubles=(double[])obj;
final int len=doubles.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
write(ID_PRIM_DOUBLE);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
write(ID_PRIM_DOUBLE);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
write(ID_PRIM_DOUBLE);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
write(ID_PRIM_DOUBLE);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
write(ID_DOUBLE_ARRAY_CLASS);
writeInt(len);
for (int i=0; i < len; i++) {
writeDouble(doubles[i]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CC_HASH_SET:
case ID_CC_LINKED_HASH_SET:
case ID_CC_TREE_SET:
case ID_CC_ARRAY_LIST:
case ID_CC_LINKED_LIST:
{
instanceCache.put(obj,instanceSeq++);
final Collection<?> collection=(Collection<?>)obj;
final int len=collection.size();
if (len == 0) {
write(unshared ? ID_COLLECTION_EMPTY_UNSHARED : ID_COLLECTION_EMPTY);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
for (Object o : collection) {
doWriteObject(o,false);
}
}
 else if (len <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(len);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
for (Object o : collection) {
doWriteObject(o,false);
}
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(len);
write(id);
if (id == ID_CC_TREE_SET) {
doWriteObject(((TreeSet)collection).comparator(),false);
}
for (Object o : collection) {
doWriteObject(o,false);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CC_HASH_MAP:
case ID_CC_HASHTABLE:
case ID_CC_IDENTITY_HASH_MAP:
case ID_CC_LINKED_HASH_MAP:
case ID_CC_TREE_MAP:
{
instanceCache.put(obj,instanceSeq++);
final Map<?,?> map=(Map<?,?>)obj;
final int len=map.size();
if (len == 0) {
write(unshared ? ID_COLLECTION_EMPTY_UNSHARED : ID_COLLECTION_EMPTY);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
for (Map.Entry<?,?> entry : map.entrySet()) {
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
}
}
 else if (len <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(len);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
for (Map.Entry<?,?> entry : map.entrySet()) {
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
}
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(len);
write(id);
if (id == ID_CC_TREE_MAP) {
doWriteObject(((TreeMap)map).comparator(),false);
}
for (Map.Entry<?,?> entry : map.entrySet()) {
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_EMPTY_MAP_OBJECT:
case ID_EMPTY_SET_OBJECT:
case ID_EMPTY_LIST_OBJECT:
{
write(id);
return;
}
case ID_SINGLETON_MAP_OBJECT:
{
instanceCache.put(obj,instanceSeq++);
write(id);
final Map.Entry entry=(Map.Entry)((Map)obj).entrySet().iterator().next();
doWriteObject(entry.getKey(),false);
doWriteObject(entry.getValue(),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_SINGLETON_LIST_OBJECT:
case ID_SINGLETON_SET_OBJECT:
{
instanceCache.put(obj,instanceSeq++);
write(id);
doWriteObject(((Collection)obj).iterator().next(),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case -1:
break;
default :
throw new NotSerializableException(objClass.getName());
}
if (isArray) {
instanceCache.put(obj,instanceSeq++);
final Object[] objects=(Object[])obj;
final int len=objects.length;
if (configuredVersion >= 2) {
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
writeClass(objClass.getComponentType());
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
writeClass(objClass.getComponentType());
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
 else if (len <= 65536) {
write(unshared ? ID_ARRAY_MEDIUM_UNSHARED : ID_ARRAY_MEDIUM);
writeShort(len);
writeClass(objClass.getComponentType());
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
 else {
write(unshared ? ID_ARRAY_LARGE_UNSHARED : ID_ARRAY_LARGE);
writeInt(len);
writeClass(objClass.getComponentType());
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
}
 else {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
writeObjectArrayClass(objClass);
writeInt(len);
for (int i=0; i < len; i++) {
doWriteObject(objects[i],unshared);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (Proxy.isProxyClass(objClass)) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
instanceCache.put(obj,instanceSeq++);
writeProxyClass(objClass);
doWriteObject(Proxy.getInvocationHandler(obj),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
Externalizer externalizer;
if (externalizers.containsKey(objClass)) {
externalizer=externalizers.get(objClass);
}
 else {
externalizer=classExternalizerFactory.getExternalizer(objClass);
externalizers.put(objClass,externalizer);
}
if (externalizer != null) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
writeExternalizerClass(objClass,externalizer);
instanceCache.put(obj,instanceSeq++);
final ObjectOutput objectOutput;
objectOutput=getObjectOutput();
externalizer.writeExternal(obj,objectOutput);
writeEndBlock();
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (obj instanceof Externalizable) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
instanceCache.put(obj,instanceSeq++);
final Externalizable ext=(Externalizable)obj;
final ObjectOutput objectOutput=getObjectOutput();
writeExternalizableClass(objClass);
ext.writeExternal(objectOutput);
writeEndBlock();
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (obj instanceof Serializable) {
write(unshared ? ID_NEW_OBJECT_UNSHARED : ID_NEW_OBJECT);
writeSerializableClass(objClass);
instanceCache.put(obj,instanceSeq++);
doWriteSerializableObject(info,obj,objClass);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
throw new NotSerializableException(objClass.getName());
}
  finally {
if (!unreplaced && obj != original) {
final int replId=instanceCache.get(obj,-1);
if (replId != -1) {
instanceCache.put(original,replId);
}
}
}
}