docs: @Override
      public void run() {
          final boolean isTraceOn = TraceComponent.isAnyTracingEnabled();
          if (isTraceOn && tc.isEntryEnabled())
              Tr.entry(tc, "run : async method " + methodInfos[ivMethodId].getMethodName() + " : " + this);
  
          // F743-22763
          // Add this methods wait time to the PMI statistics and decrement
          // the queue size if PMI is enabled and startTime was successfully set.
          if ((ivPmiBean != null) && (ivStartTime > 0)) {
              ivPmiBean.finalTime(EJBPMICollaborator.ASYNC_WAIT_TIME, ivStartTime);
              ivPmiBean.asyncQueSizeDecrement();
          }
  
          // Result from the async method call
          Future<?> theResult = null;
  
          EJBMethodInfoImpl methodInfo = methodInfos[ivMethodId];
          Method theMethod = methodInfo.ivMethod;
  
          EJSDeployedSupport s = new EJSDeployedSupport();
  
          // Provide the server result to the method context to support
          // EJBContext.wasCancelled().
          s.ivAsyncResult = ivServerFuture;
  
          boolean isVoidReturnType = (theMethod.getReturnType() == Void.TYPE); // F743-22763
  
          // F743761.CodRv - Void methods do not throw application exceptions.
          s.ivIgnoreApplicationExceptions = isVoidReturnType;
  
          AbstractEJBRuntime rt = (AbstractEJBRuntime) super.container.getEJBRuntime();
  
          // If the server is stopping, don't invoke the async method
          if (rt.isStopping()) {
              if (isTraceOn && tc.isDebugEnabled())
                  Tr.debug(tc, "Async method " + methodInfo.getBeanClassName() + "." + methodInfo.getMethodName() + " will not be invoked because server is stopping");
          } else {
              try {
                  try {
                      Object theBean = container.EjbPreInvoke(this, ivMethodId, s, ivArgs);
  
                      // If preInvoke did not have an exception, continue on and invoke the
                      // bean's method, using the reflection object or via interceptors.
                      // F743-24429
                      if (methodInfo.getAroundInterceptorProxies() == null) {
                          try {
                              theResult = (Future<?>) theMethod.invoke(theBean, ivArgs); // d650178
                          } catch (InvocationTargetException ite) {
                              if (isTraceOn && tc.isDebugEnabled())
                                  Tr.debug(tc, "Caught InvocationTargetException, unwrapping : " + ite);
                              throw ite.getCause(); // PI13514
                          }
                      } else {
                          theResult = (Future<?>) container.invoke(s, (Timer) null); // d650178
                      }
  
                      // Note: results are not set in the server result future yet,
                      // as there may still be an exception during postInvoke.
  
                      if (isTraceOn && tc.isDebugEnabled())
                          Tr.debug(tc, "Async method completed successfully");
                  } catch (Throwable ex) {
                      // For void methods, metadata validation has already ensured that
                      // the throws clause is empty, so declared will always be false.
                      boolean declared = isApplicationException(ex, methodInfo); // d660332
  
                      if (isTraceOn && tc.isDebugEnabled())
                          Tr.debug(tc, "Caught Throwable (declared=" + declared + "): " + ex);
  
                      // Update deployed support so postInvoke will handle the exception.
                      if (declared) {
                          // F743-761 - Simulate synchronous wrappers by calling
                          // setCheckedException for exceptions on the throws clause.
                          s.setCheckedException((Exception) ex);
                          throw ex;
                      }
  
                      // For void methods, ivIgnoreApplicationExceptions is true, so
                      // setUncheckedLocalException will always log this exception and
                      // then throw EJBException.
                      s.setUncheckedLocalException(ex);
                  } finally {
                      try {
                          container.postInvoke(this, ivMethodId, s);
                      } catch (RemoteException re) {
                          // This should never occur, but must be caught, since
                          // RemoteException is on the throws clause of postInvoke.
                          FFDCFilter.processException(re, CLASS_NAME + ".run", "242", this);
                          s.setUncheckedLocalException(re);
                      }
                  }
              } catch (Throwable ex) {
                  // Unchecked Exceptions will have already been logged with FFDC
                  // above, no need to repeat that here.
  
                  if (isTraceOn && tc.isDebugEnabled())
                      Tr.debug(tc, "Async method completed with exception : " + ex);
  
                  // If there is a server-side future object set the exception there
                  // too.  FireAndForget async methods will not have a server-side
                  // future object so the exception cannot be reported.
                  if (ivServerFuture != null) {
                      // This wrapper class has to act like a stub class. In the remote
                      // code path, the container has already mapped RemoteException to
                      // SystemException for it to be sent to the ORB
                      // (OrbUtilsImpl.mapException). Since the resulting exception will
                      // never go through the ORB directly (we're catching it here, and
                      // RemoteAsyncResultImpl will wrap it in ExecutionException), we
                      // need to do the reverse operation and map from SystemException
                      // back to RemoteException just like a generated stub would do.
                      ex = mapSystemExceptionBackToRemoteException(ex);
  
                      ivServerFuture.setException(ex);
                  }
  
                  // F743-22763
                  // For fire and forget methods, if PMI statistics are being collected
                  // increment the number of fire and forget methods failed counter
                  if ((ivPmiBean != null) && isVoidReturnType) {
                      ivPmiBean.asyncFNFFailed();
                  }
  
                  if (isTraceOn && tc.isEntryEnabled())
                      Tr.exit(tc, "run : " + ex);
                  return;
              }
          }
  
          // If a server-side future object is present, the async method is
          // supposed to return results. Otherwise, it is a "fire-and-forget"
          // type method, where no results are returned. Note: null is a
          // valid method result so we can't use a result == null check here
          // to identify a "fire-and-forget" type method.
          if (ivServerFuture != null) {
              ivServerFuture.setResult(theResult);
          }
  
          if (isTraceOn && tc.isEntryEnabled())
              Tr.exit(tc, "run");
      }