docs: @Override
      public final synchronized void destroy() {
          final boolean isTraceOn = TraceComponent.isAnyTracingEnabled();
          if (isTraceOn && tc.isEntryEnabled()) // d367572.4
          {
              Tr.entry(tc, "destroy");
          }
  
          if (state == DESTROYED) {
              return;
          }
  
          // For Stateless, 'destroy' is where the bean is removed and destroyed.
          // Remove time should include calling any lifecycle callbacks.   d626533.1
          long removeStartTime = -1;
          if (pmiBean != null) {
              removeStartTime = pmiBean.initialTime(EJBPMICollaborator.REMOVE_RT);
          }
  
          allowRollbackOnly = false;
  
          if (ivCallbackKind != CallbackKind.None) {
              // d367572.4 start of change.
              String lifeCycle = null;
              CallbackContextHelper contextHelper = new CallbackContextHelper(this); // d399469, d630940
              BeanMetaData bmd = home.beanMetaData;
  
              try {
                  // Suspend UOW to ensure everything in this method runs
                  // in a unspecified TX context if this bean is in a EJB 3.0
                  // module.  We are not doing for older modules to ensure we do
                  // break existing working applications.
                  //
                  // Pre-Destroy is allowed to access java:comp/env, so all contexts
                  // must be established around the Pre-Destroy calls. This must be done
                  // for Stateless beans since they are often destroyed outside the scope
                  // of a method invocation.                                      d546031
                  contextHelper.begin(CallbackContextHelper.Tx.CompatLTC,
                                      CallbackContextHelper.Contexts.All);
  
                  // d367572.1 start
                  // Invoke either ejbRemove or PreDestroy lifecycle callback if necessary.
                  if (ivCallbackKind == CallbackKind.SessionBean) {
                      if (isTraceOn && // d527372
                          TEBeanLifeCycleInfo.isTraceEnabled()) {
                          lifeCycle = "ejbRemove";
                          TEBeanLifeCycleInfo.traceEJBCallEntry(lifeCycle); // d161864
                      }
  
                      // pre-EJB3 SLSB, so invoke ejbRemove.
                      sessionBean.ejbRemove();
                  } else if (ivCallbackKind == CallbackKind.InvocationContext) {
                      // Invoke the PreDestroy interceptor methods.
                      if (isTraceOn && // d527372
                          TEBeanLifeCycleInfo.isTraceEnabled()) {
                          lifeCycle = "preDestroy";
                          TEBeanLifeCycleInfo.traceEJBCallEntry(lifeCycle); // d161864
                      }
                      InterceptorMetaData imd = home.beanMetaData.ivInterceptorMetaData;
                      InterceptorProxy[] proxies = imd.ivPreDestroyInterceptors;
                      if (proxies != null) {
                          if (isTraceOn && tc.isDebugEnabled()) {
                              Tr.debug(tc, "invoking PreDestroy interceptors");
                          }
                          InvocationContextImpl<?> inv = getInvocationContext();
                          inv.doLifeCycle(proxies, bmd._moduleMetaData); //d450431, F743-14982
                      }
                  } // d367572.1 end
              } catch (Exception ex) {
                  FFDCFilter.processException(ex, CLASS_NAME + ".destroy", "164", this);
  
                  // Just trace this event and continue so that BeanO is transitioned
                  // to the DESTROYED state.  No other lifecycle callbacks on this bean
                  // instance will occur once in the DESTROYED state, which is the same
                  // affect as if bean was discarded as result of this exception.
                  if (isTraceOn && tc.isEventEnabled()) {
                      Tr.event(tc, "destroy caught exception: ", new Object[] { this, ex }); // d402681
                  }
              } finally {
                  if (isTraceOn && // d527372
                      TEBeanLifeCycleInfo.isTraceEnabled()) {
                      if (lifeCycle != null) {
                          TEBeanLifeCycleInfo.traceEJBCallExit(lifeCycle); // d161864
                      }
                  }
  
                  try {
                      contextHelper.complete(true);
                  } catch (Throwable t) {
                      FFDCFilter.processException(t, CLASS_NAME + ".destroy", "505", this);
  
                      // Just trace this event and continue so that BeanO is transitioned
                      // to the DESTROYED state.  No other lifecycle callbacks on this bean
                      // instance will occur once in the DESTROYED state, which is the same
                      // affect as if bean was discarded as result of this exception.
                      if (isTraceOn && tc.isEventEnabled()) {
                          Tr.event(tc, "destroy caught exception: ", new Object[] { this, t });
                      }
                  }
              } // d367572.4 end of change.
          }
  
          setState(DESTROYED);
  
          destroyHandleList();
  
          // Release any JCDI creational contexts that may exist.         F743-29174
          releaseManagedObjectContext();
  
          // For Stateless, 'destroy' is where the bean is removed and destroyed.
          // Update both counters and end remove time.                     d626533.1
          if (pmiBean != null) {
              pmiBean.beanRemoved(); // d647928.4
              pmiBean.beanDestroyed();
              pmiBean.finalTime(EJBPMICollaborator.REMOVE_RT, removeStartTime);
          }
  
          // If the number of allowed bean instances is limited, then the number
          // of created instances needs to be decremented when an instance is
          // destroyed, and the next thread that may be waiting for an instance
          // must be notified.                                               PK20648
          if (ivNumberOfBeansLimited) {
              synchronized (beanPool) {
                  --home.ivNumberBeansCreated;
                  if (isTraceOn && tc.isDebugEnabled())
                      Tr.debug(tc, "destroy: BeanPool(" + home.ivNumberBeansCreated +
                                   "/" + home.beanMetaData.ivMaxCreation + ")");
                  beanPool.notify();
              }
          }
  
          allowRollbackOnly = true;
  
          if (isTraceOn && tc.isEntryEnabled()) // d367572.4
          {
              Tr.exit(tc, "destroy");
          }
      }