Program: 42974
Project: 42974
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) {
        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);
        }
 else {
          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=getBasicClasses(configuredVersion).get(objClass,-1);
      if (id == ID_CLASS_CLASS) {
        final Class<?> classObj=(Class<?>)obj;
        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:
{
            write(ID_NEW_OBJECT);
            writeClassClass(classObj);
            return;
          }
default :
{
          write(cid);
          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:
{
    write(ID_BYTE_OBJECT);
    writeByte(((Byte)obj).byteValue());
    return;
  }
case ID_BOOLEAN_CLASS:
{
  write(((Boolean)obj).booleanValue() ? ID_BOOLEAN_OBJECT_TRUE : ID_BOOLEAN_OBJECT_FALSE);
  return;
}
case ID_CHARACTER_CLASS:
{
write(ID_CHARACTER_OBJECT);
writeChar(((Character)obj).charValue());
return;
}
case ID_DOUBLE_CLASS:
{
write(ID_DOUBLE_OBJECT);
writeDouble(((Double)obj).doubleValue());
return;
}
case ID_FLOAT_CLASS:
{
write(ID_FLOAT_OBJECT);
writeFloat(((Float)obj).floatValue());
return;
}
case ID_INTEGER_CLASS:
{
write(ID_INTEGER_OBJECT);
writeInt(((Integer)obj).intValue());
return;
}
case ID_LONG_CLASS:
{
write(ID_LONG_OBJECT);
writeLong(((Long)obj).longValue());
return;
}
case ID_SHORT_CLASS:
{
write(ID_SHORT_OBJECT);
writeShort(((Short)obj).shortValue());
return;
}
case ID_STRING_CLASS:
{
final String string=(String)obj;
final int len=string.length();
if (len == 0) {
write(ID_STRING_EMPTY);
return;
}
 else if (len <= 0x100) {
write(ID_STRING_SMALL);
write(len);
}
 else if (len <= 0x10000) {
write(ID_STRING_MEDIUM);
writeShort(len);
}
 else {
write(ID_STRING_LARGE);
writeInt(len);
}
shallowFlush();
UTFUtils.writeUTFBytes(byteOutput,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 (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);
}
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 (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);
}
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 (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]);
}
}
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 (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]);
}
}
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 (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]);
}
}
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 (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]);
}
}
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 (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]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_DOUBLE_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final double[] doubles=(double[])obj;
final int len=doubles.length;
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]);
}
}
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:
case ID_CC_VECTOR:
case ID_CC_STACK:
case ID_CC_ARRAY_DEQUE:
{
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_ENUM_SET_PROXY:
{
final Enum[] elements=getEnumSetElements(obj);
final int len=elements.length;
if (len == 0) {
write(unshared ? ID_COLLECTION_EMPTY_UNSHARED : ID_COLLECTION_EMPTY);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
for (Object o : elements) {
doWriteObject(o,false);
}
}
 else if (len <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(len);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
for (Object o : elements) {
doWriteObject(o,false);
}
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(len);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
for (Object o : elements) {
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:
case ID_CC_ENUM_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);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
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);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
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);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
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:
case ID_REVERSE_ORDER_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 ID_REVERSE_ORDER2_OBJECT:
{
instanceCache.put(obj,instanceSeq++);
write(id);
try {
doWriteObject(Protocol.reverseOrder2Field.get(obj),false);
}
 catch (IllegalAccessException e) {
throw new InvalidObjectException("String_Node_Str");
}
return;
}
case ID_CC_CONCURRENT_HASH_MAP:
case ID_CC_COPY_ON_WRITE_ARRAY_LIST:
case ID_CC_COPY_ON_WRITE_ARRAY_SET:
{
info=registry.lookup(objClass);
break;
}
case ID_PAIR:
{
instanceCache.put(obj,instanceSeq++);
write(id);
Pair<?,?> pair=(Pair<?,?>)obj;
doWriteObject(pair.getA(),unshared);
doWriteObject(pair.getB(),unshared);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CC_NCOPIES:
{
List<?> list=(List<?>)obj;
int size=list.size();
if (size == 0) {
write(ID_EMPTY_LIST_OBJECT);
return;
}
instanceCache.put(obj,instanceSeq++);
if (size <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(size);
}
 else if (size <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(size);
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(size);
}
write(id);
doWriteObject(list.iterator().next(),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case -1:
break;
default :
throw new NotSerializableException(objClass.getName());
}
if (isArray) {
final Object[] objects=(Object[])obj;
final int len=objects.length;
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
writeClass(objClass.getComponentType());
instanceCache.put(obj,instanceSeq++);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
writeClass(objClass.getComponentType());
instanceCache.put(obj,instanceSeq++);
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());
instanceCache.put(obj,instanceSeq++);
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());
instanceCache.put(obj,instanceSeq++);
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);
final Externalizable ext=(Externalizable)obj;
final ObjectOutput objectOutput=getObjectOutput();
writeExternalizableClass(objClass);
instanceCache.put(obj,instanceSeq++);
ext.writeExternal(objectOutput);
writeEndBlock();
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (serializabilityChecker.isSerializable(objClass)) {
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) {
        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);
        }
 else {
          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=getBasicClasses(configuredVersion).get(objClass,-1);
      if (id == ID_CLASS_CLASS) {
        final Class<?> classObj=(Class<?>)obj;
        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:
{
            write(ID_NEW_OBJECT);
            writeClassClass(classObj);
            return;
          }
default :
{
          write(cid);
          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:
{
    write(ID_BYTE_OBJECT);
    writeByte(((Byte)obj).byteValue());
    return;
  }
case ID_BOOLEAN_CLASS:
{
  write(((Boolean)obj).booleanValue() ? ID_BOOLEAN_OBJECT_TRUE : ID_BOOLEAN_OBJECT_FALSE);
  return;
}
case ID_CHARACTER_CLASS:
{
write(ID_CHARACTER_OBJECT);
writeChar(((Character)obj).charValue());
return;
}
case ID_DOUBLE_CLASS:
{
write(ID_DOUBLE_OBJECT);
writeDouble(((Double)obj).doubleValue());
return;
}
case ID_FLOAT_CLASS:
{
write(ID_FLOAT_OBJECT);
writeFloat(((Float)obj).floatValue());
return;
}
case ID_INTEGER_CLASS:
{
write(ID_INTEGER_OBJECT);
writeInt(((Integer)obj).intValue());
return;
}
case ID_LONG_CLASS:
{
write(ID_LONG_OBJECT);
writeLong(((Long)obj).longValue());
return;
}
case ID_SHORT_CLASS:
{
write(ID_SHORT_OBJECT);
writeShort(((Short)obj).shortValue());
return;
}
case ID_STRING_CLASS:
{
final String string=(String)obj;
final int len=string.length();
if (len == 0) {
write(ID_STRING_EMPTY);
return;
}
 else if (len <= 0x100) {
write(ID_STRING_SMALL);
write(len);
}
 else if (len <= 0x10000) {
write(ID_STRING_MEDIUM);
writeShort(len);
}
 else {
write(ID_STRING_LARGE);
writeInt(len);
}
shallowFlush();
UTFUtils.writeUTFBytes(byteOutput,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 (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);
}
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 (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);
}
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 (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]);
}
}
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 (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]);
}
}
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 (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]);
}
}
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 (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]);
}
}
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 (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]);
}
}
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_DOUBLE_ARRAY_CLASS:
{
if (!unshared) {
instanceCache.put(obj,instanceSeq++);
}
final double[] doubles=(double[])obj;
final int len=doubles.length;
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]);
}
}
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:
case ID_CC_VECTOR:
case ID_CC_STACK:
case ID_CC_ARRAY_DEQUE:
{
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_ENUM_SET_PROXY:
{
final Enum[] elements=getEnumSetElements(obj);
final int len=elements.length;
if (len == 0) {
write(unshared ? ID_COLLECTION_EMPTY_UNSHARED : ID_COLLECTION_EMPTY);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
for (Object o : elements) {
doWriteObject(o,false);
}
}
 else if (len <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(len);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
for (Object o : elements) {
doWriteObject(o,false);
}
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(len);
write(id);
writeClass(getEnumSetElementType(obj));
instanceCache.put(obj,instanceSeq++);
for (Object o : elements) {
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:
case ID_CC_ENUM_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);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
}
 else if (len <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(len);
write(id);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
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);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
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);
switch (id) {
case ID_CC_TREE_MAP:
doWriteObject(((TreeMap)map).comparator(),false);
break;
case ID_CC_ENUM_MAP:
writeClass(getEnumMapKeyType(obj));
break;
}
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:
case ID_REVERSE_ORDER_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 ID_REVERSE_ORDER2_OBJECT:
{
instanceCache.put(obj,instanceSeq++);
write(id);
try {
doWriteObject(Protocol.reverseOrder2Field.get(obj),false);
}
 catch (IllegalAccessException e) {
throw new InvalidObjectException("String_Node_Str");
}
return;
}
case ID_CC_CONCURRENT_HASH_MAP:
case ID_CC_COPY_ON_WRITE_ARRAY_LIST:
case ID_CC_COPY_ON_WRITE_ARRAY_SET:
{
info=registry.lookup(objClass);
break;
}
case ID_PAIR:
{
instanceCache.put(obj,instanceSeq++);
write(id);
Pair<?,?> pair=(Pair<?,?>)obj;
doWriteObject(pair.getA(),unshared);
doWriteObject(pair.getB(),unshared);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case ID_CC_NCOPIES:
{
List<?> list=(List<?>)obj;
int size=list.size();
if (size == 0) {
write(ID_EMPTY_LIST_OBJECT);
return;
}
instanceCache.put(obj,instanceSeq++);
if (size <= 256) {
write(unshared ? ID_COLLECTION_SMALL_UNSHARED : ID_COLLECTION_SMALL);
write(size);
}
 else if (size <= 65536) {
write(unshared ? ID_COLLECTION_MEDIUM_UNSHARED : ID_COLLECTION_MEDIUM);
writeShort(size);
}
 else {
write(unshared ? ID_COLLECTION_LARGE_UNSHARED : ID_COLLECTION_LARGE);
writeInt(size);
}
write(id);
doWriteObject(list.iterator().next(),false);
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
case -1:
break;
default :
throw new NotSerializableException(objClass.getName());
}
if (isArray) {
final Object[] objects=(Object[])obj;
final int len=objects.length;
if (len == 0) {
write(unshared ? ID_ARRAY_EMPTY_UNSHARED : ID_ARRAY_EMPTY);
writeClass(objClass.getComponentType());
instanceCache.put(obj,instanceSeq++);
}
 else if (len <= 256) {
write(unshared ? ID_ARRAY_SMALL_UNSHARED : ID_ARRAY_SMALL);
write(len);
writeClass(objClass.getComponentType());
instanceCache.put(obj,instanceSeq++);
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());
instanceCache.put(obj,instanceSeq++);
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());
instanceCache.put(obj,instanceSeq++);
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);
writeProxyClass(objClass);
instanceCache.put(obj,instanceSeq++);
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);
final Externalizable ext=(Externalizable)obj;
final ObjectOutput objectOutput=getObjectOutput();
writeExternalizableClass(objClass);
instanceCache.put(obj,instanceSeq++);
ext.writeExternal(objectOutput);
writeEndBlock();
if (unshared) {
instanceCache.put(obj,-1);
}
return;
}
if (serializabilityChecker.isSerializable(objClass)) {
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);
}
}
}
}