@SuppressWarnings("unchecked")
  public static <T> T copy(T o) {
    T copy = null;
    try {
      if (o == null) {
        return null;
      } else if (o instanceof Token) {
        return o;
      } else {
        if (isWellKnownImmutableInstance(o)) {
          return o;
        }
        if (o instanceof Cloneable) {
          try {
            // Note that Object.clone is protected so we need to use reflection
            // to call clone even though this object implements Cloneable
            Class<?> c = o.getClass();
            // By convention, the user should make the clone method public.
            // But even if they don't, let's go ahead and use it.
            // The other problem is that if the class is private, we still
            // need to make the method accessible even if the method is public,
            // because Object.clone is protected.
            Method m = c.getDeclaredMethod("clone");
            m.setAccessible(true);
            copy = (T) m.invoke(o, new Object[0]);
            return copy;
          } catch (NoSuchMethodException | IllegalAccessException | SecurityException ignore) {
            // try using Serialization
          } catch (InvocationTargetException ex) {
            Throwable cause = ex.getTargetException();
            if (cause instanceof CloneNotSupportedException) {
              // try using Serialization
            } else {
              throw new CopyException("Clone failed.",
                  cause != null ? cause : ex);
            }
          }
        } else if (o instanceof CachedDeserializable) {
          copy = (T) ((CachedDeserializable) o).getDeserializedWritableCopy(null, null);
          return copy;
        }
        // Copy using serialization
        copy = doDeepCopy(o);
        return copy;
      }
    } finally {
      if (copy != null) {
        PdxUnreadData.copy(o, copy);
      }
    }
  }
<p>
Makes a copy of the specified object. The object returned is not guaranteed to be a deep copy
of the original object, as explained below.

<p>
Copies can only be made if the original is a <tt>Cloneable</tt> or serializable by GemFire. If
o is a {@link #isWellKnownImmutableInstance(Object) well known immutable instance} then it will
be returned without copying it.

<p>
If the argument o is an instance of {@link java.lang.Cloneable}, a copy is made by invoking
<tt>clone</tt> on it. Note that not all implementations of <tt>clone</tt> make deep copies
(e.g. {@link java.util.HashMap#clone HashMap.clone}). Otherwise, if the argument is not an
instance of <tt>Cloneable</tt>, a copy is made using serialization: if GemFire serialization is
implemented, it is used; otherwise, java serialization is used.

<p>
The difference between this method and {@link #deepCopy(Object) deepCopy}, is that this method
uses <tt>clone</tt> if available, whereas <tt>deepCopy</tt> does not. As a result, for
<tt>Cloneable</tt> objects copied using this method, how deep a copy the returned object is
depends on its implementation of <tt>clone</tt>.

@param <T> the type of the object to be copied
@param o the original object that a copy is needed of
@return the new instance that is a copy of of the original
@throws CopyException if copying fails because a class could not be found or could not be
        serialized.
@see #deepCopy(Object)
@since GemFire 4.0
geode-core/src/main/java/org/apache/geode/CopyHelper.java