public static LiveRef read(ObjectInput in, boolean useNewFormat)
      throws IOException, ClassNotFoundException {
    Endpoint ep;
    ObjID id;

    // Now read in the endpoint, id, and result flag
    // (need to choose whether or not to read old JDK1.1 endpoint format)
    if (useNewFormat) {
      ep = TCPEndpoint.read(in);
    } else {
      ep = TCPEndpoint.readHostPortFormat(in);
    }
    id = ObjID.read(in);
    boolean isResultStream = in.readBoolean();

    LiveRef ref = new LiveRef(id, ep, false);

    if (in instanceof ConnectionInputStream) {
      ConnectionInputStream stream = (ConnectionInputStream) in;
      // save ref to send "dirty" call after all args/returns
      // have been unmarshaled.
      stream.saveRef(ref);
      if (isResultStream) {
        // set flag in stream indicating that remote objects were
        // unmarshaled.  A DGC ack should be sent by the transport.
        stream.setAckNeeded();
      }
    } else {
      DGCClient.registerRefs(ep, Arrays.asList(new LiveRef[] {ref}));
    }

    return ref;
  }
  private static void incomingMessageCall(UnicastConnection conn) throws IOException {
    ObjectInputStream in = conn.startObjectInputStream(); // (re)start ObjectInputStream

    ObjID objid = ObjID.read(in);
    int method = in.readInt();
    long hash = in.readLong();

    // System.out.println("ObjID: " + objid + ", method: " + method + ", hash: " + hash);

    // Use the objid to locate the relevant UnicastServerRef
    UnicastServerRef uref = (UnicastServerRef) objects.get(objid);
    Object returnval;
    int returncode = RETURN_ACK;
    // returnval is from Method.invoke(), so we must check the return class to see
    // if it's primitive type
    Class returncls = null;
    if (uref != null) {
      try {
        // Dispatch the call to it.
        returnval = uref.incomingMessageCall(conn, method, hash);
        returncls = uref.getMethodReturnType(method, hash);
      } catch (Exception e) {
        returnval = e;
        returncode = RETURN_NACK;
      } catch (Error e) {
        returnval =
            new ServerError("An Error is thrown while processing the invocation on the server", e);
        returncode = RETURN_NACK;
      }
    } else {
      returnval = new NoSuchObjectException("");
      returncode = RETURN_NACK;
    }

    conn.getDataOutputStream().writeByte(MESSAGE_CALL_ACK);

    ObjectOutputStream out = conn.startObjectOutputStream(); // (re)start ObjectOutputStream

    out.writeByte(returncode);
    (new UID()).write(out);

    // System.out.println("returnval=" + returnval + " returncls=" + returncls);

    if (returnval != null && returncls != null)
      ((RMIObjectOutputStream) out).writeValue(returnval, returncls);

    // 1.1/1.2 void return type detection:
    else if (!(returnval instanceof RMIVoidValue || returncls == Void.TYPE))
      out.writeObject(returnval);

    out.flush();
  }