protected <O> O instantiate(int id, DataContainer container, ClassTypeModel<O> typeModel)
      throws IOException {
    Map<FieldModel<? super O, ?>, Object> state = new HashMap<FieldModel<? super O, ?>, Object>();
    ClassTypeModel<? super O> currentTypeModel = typeModel;
    List<FieldUpdate<O>> sets = new ArrayList<FieldUpdate<O>>();
    while (currentTypeModel != null) {
      if (currentTypeModel instanceof ClassTypeModel) {
        for (FieldModel<? super O, ?> fieldModel : currentTypeModel.getFields()) {
          if (!fieldModel.isTransient()) {
            switch (container.readInt()) {
              case DataKind.NULL_VALUE:
                state.put(fieldModel, null);
                break;
              case DataKind.OBJECT_REF:
                int refId = container.readInt();
                Object refO = idToObject.get(refId);
                if (refO != null) {
                  state.put(fieldModel, refO);
                } else {
                  sets.add(new FieldUpdate<O>(refId, fieldModel));
                }
                break;
              case DataKind.OBJECT:
                Object o = container.readObject();
                state.put(fieldModel, o);
                break;
            }
          }
        }
      }
      currentTypeModel = currentTypeModel.getSuperType();
    }

    //
    O instance = instantiate(typeModel, state);

    // Create future field updates
    for (FieldUpdate<O> set : sets) {
      List<FutureFieldUpdate<?>> resolutions = idToResolutions.get(set.ref);
      if (resolutions == null) {
        resolutions = new ArrayList<FutureFieldUpdate<?>>();
        idToResolutions.put(set.ref, resolutions);
      }
      resolutions.add(new FutureFieldUpdate<O>(instance, set.fieldModel));
    }

    //
    idToObject.put(id, instance);

    // Resolve future field updates
    List<FutureFieldUpdate<?>> resolutions = idToResolutions.remove(id);
    if (resolutions != null) {
      for (FutureFieldUpdate<?> resolution : resolutions) {
        resolution.fieldModel.castAndSet(resolution.target, instance);
      }
    }

    //
    return instance;
  }
  private <O> O instantiate(ClassTypeModel<O> typeModel, Map<FieldModel<? super O, ?>, ?> state)
      throws InvalidClassException {
    try {
      ObjectFactory<? super O> factory = context.getFactory(typeModel.getJavaType());

      //
      return factory.create(typeModel.getJavaType(), state);
    } catch (Exception e) {
      InvalidClassException ice =
          new InvalidClassException(
              "Cannot instantiate object from class " + typeModel.getJavaType().getName());
      ice.initCause(e);
      throw ice;
    }
  }