docs: JsMsgObject getCopy() throws MessageCopyFailedException {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "getCopy");
  
      JsMsgObject newJmo = null;
  
  
      try {
  
        // We need to lock the whole of the copy with the getHdr2, getApi & getPayload
        // methods on the owning message, otherwise someone could reinstate the partcaches
        // between clearing them and creating the new parts.               d352642
        synchronized(theMessage) {
  
          // Ensure any cached message data is written back and cached message parts are
          // invalidated.
          theMessage.updateDataFields(MfpConstants.UDF_GET_COPY);
          theMessage.clearPartCaches();
  
          // Clone this JMO and insert a copy of the underlying JMF message.  It is the JMF
          // that handles all the "lazy" copying.
          newJmo = new JsMsgObject(null);
          newJmo.headerPart = new JsMsgPart(((JMFMessage)headerPart.jmfPart).copy());
          newJmo.payloadPart = new JsMsgPart(((JMFMessage)payloadPart.jmfPart).copy());
        }
  
      } catch (MessageDecodeFailedException e) {
        // Dump whatever we can of both message parts
        FFDCFilter.processException(e, "com.ibm.ws.sib.mfp.impl.JsMsgObject.getCopy", "jmo800", this,
            new Object[] {
              new Object[] { MfpConstants.DM_MESSAGE, headerPart.jmfPart, theMessage },
              new Object[] { MfpConstants.DM_MESSAGE, payloadPart.jmfPart, theMessage }
            }
          );
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "copy failed: " + e);
        throw new MessageCopyFailedException(e);
      }
  
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "getCopy", newJmo);
      return newJmo;
    }