docs: private final JsMessage restoreJsMessage(byte[] buffer, Object store) throws MessageRestoreFailedException {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(tc, "restoreJsMessage" , buffer);
  
      JsMessage newMsg = null;
  
      String className;
      int offset = 0;
  
      /* The buffer contains:                                                   */
      /*     the message class name                                             */
      /*     the list of JMF schema ids needed to decode the message            */
      /*     the message itself                                                 */
      // Trace the first 256 bytes just in case we get passed rubbish
      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Start of buffer: ", SibTr.formatBytes(buffer, 0, 256));
  
      // Extract the classname from the buffer
      int temp = ArrayUtil.readInt(buffer, offset);               // the length of the class name
      offset += ArrayUtil.INT_SIZE;
      try {
        className = getClassName(buffer, offset, temp);         // the class name itself
      }
      catch (RuntimeException e) {
        FFDCFilter.processException(e, "com.ibm.ws.sib.mfp.impl.JsMessageFactoryImpl.restoreJsMessage", "573", this,
                                                new Object[]{ MfpConstants.DM_BUFFER, buffer, 0, buffer.length});
        // This is a disaster - presumably the buffer is garbage - so we have to throw the exception on
        throw new MessageRestoreFailedException(e);
      }
      offset += temp;
  
      // Extract the message schema ids from the buffer, & ensure the schemas are available.
      offset = ensureSchemasAvailable(buffer, offset, store);
  
      try {
        /* Create a new JMO from the remaining buffer  */
        JsMsgObject newJmo = new JsMsgObject(JsHdrAccess.schema, JsPayloadAccess.schema, buffer, offset, buffer.length-offset);
  
        /* Get the class for the appropriate specialization */
        Class  msgClass = Class.forName(className);
  
        /* Now create the new JsMessage and set the JMO               */
        newMsg = (JsMessage)msgClass.newInstance();
        ((JsMessageImpl)newMsg).setJmo(newJmo);
  
        /* Set the approxLength as we know it */
        ((JsMessageImpl)newMsg).setApproximateLength(newJmo.getOriginalLength());
      }
      catch (ClassNotFoundException e1) {
        FFDCFilter.processException(e1, "com.ibm.ws.sib.mfp.impl.JsMessageFactoryImpl.restore", "534");
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Exception " + e1.toString() + " finding class " + className);
        throw new MessageRestoreFailedException(e1);
      }
      catch (MessageDecodeFailedException e2) {
        /* No need to FFDC this as JsMsgObject will already have done so */
        // No FFDC code needed
        throw new MessageRestoreFailedException(e2);
      }
      catch (Exception e3) {
        /* Any other exceptions from instantiation should never happen */
        FFDCFilter.processException(e3, "com.ibm.ws.sib.mfp.impl.JsMessageFactoryImpl.restore", "545");
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Exception " + e3.toString() + " instantiating class " + className);
        throw new MessageRestoreFailedException(e3);
      }
  
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "restoreJsMessage");
      return newMsg;
    }