private void updateExtReadersWriters(
      ExternalizerAdapter adapter, Class<?> typeClass, int readerIndex) {
    writers.put(typeClass, adapter);
    ExternalizerAdapter prevReader = readers.put(readerIndex, adapter);
    // Several externalizers might share same id (i.e. HashMap and TreeMap use MapExternalizer)
    // but a duplicate is only considered when that particular index has already been entered
    // in the readers map and the externalizers are different (they're from different classes)
    if (prevReader != null && !prevReader.equals(adapter))
      throw log.duplicateExternalizerIdFound(
          adapter.id, typeClass, prevReader.externalizer.getClass().getName(), readerIndex);

    if (log.isTraceEnabled())
      log.tracef(
          "Loaded externalizer %s for %s with id %s and reader index %s",
          adapter.externalizer.getClass().getName(), typeClass, adapter.id, readerIndex);
  }
  @Override
  public Object readObject(Unmarshaller input) throws IOException, ClassNotFoundException {
    int readerIndex = input.readUnsignedByte();
    int foreignId = -1;
    if (readerIndex == Ids.MAX_ID) {
      // User defined externalizer
      foreignId = UnsignedNumeric.readUnsignedInt(input);
      readerIndex = generateForeignReaderIndex(foreignId);
    }

    ExternalizerAdapter adapter = readers.get(readerIndex);
    if (adapter == null) {
      if (!started) {
        log.tracef(
            "Either the marshaller has stopped or hasn't started. Read externalizers are not properly populated: %s",
            readers);

        if (Thread.currentThread().isInterrupted()) {
          throw log.pushReadInterruptionDueToCacheManagerShutdown(
              readerIndex, new InterruptedException());
        } else {
          throw log.cannotResolveExternalizerReader(gcr.getStatus(), readerIndex);
        }
      } else {
        if (log.isTraceEnabled()) {
          log.tracef("Unknown type. Input stream has %s to read", input.available());
          log.tracef("Check contents of read externalizers: %s", readers);
        }

        if (foreignId > 0) throw log.missingForeignExternalizer(foreignId);

        throw log.unknownExternalizerReaderIndex(readerIndex);
      }
    }

    return adapter.readObject(input);
  }