protected void disconnect(boolean preparingForReconnect, String reason, boolean keepAlive) {
    boolean isShutdownHook = (shutdownHook != null) && (Thread.currentThread() == shutdownHook);

    if (!preparingForReconnect) {
      // logger.info("disconnecting IDS@"+System.identityHashCode(this));
      synchronized (reconnectListeners) {
        reconnectListeners.clear();
      }
      cancelReconnect();
    }

    final boolean isDebugEnabled = logger.isDebugEnabled();
    try {
      HashSet<ShutdownListener> shutdownListeners = null;
      try {
        if (isDebugEnabled) {
          logger.debug("DistributedSystem.disconnect invoked on {}", this);
        }
        synchronized (GemFireCacheImpl.class) {
          // bug 36955, 37014: don't use a disconnect listener on the cache;
          // it takes too long.
          //
          // However, make sure cache is completely closed before starting
          // the distributed system close.
          InternalCache currentCache = getCache();
          if (currentCache != null && !currentCache.isClosed()) {
            isDisconnectThread.set(Boolean.TRUE); // bug #42663 - this must be set while
            // closing the cache
            try {
              currentCache.close(reason, dm.getRootCause(), keepAlive, true, false);
            } catch (VirtualMachineError e) {
              SystemFailure.initiateFailure(e);
              throw e;
            } catch (Throwable e) {
              SystemFailure.checkFailure();
              // Whenever you catch Error or Throwable, you must also
              // check for fatal JVM error (see above). However, there is
              logger.warn(
                  "Exception trying to close cache",
                  e);
            } finally {
              isDisconnectThread.set(Boolean.FALSE);
            }
          }

          // While still holding the lock, make sure this instance is
          // marked as shutting down
          synchronized (this) {
            if (isDisconnecting) {
              // It's already started, but don't return
              // to the caller until it has completed.
              waitDisconnected();
              return;
            } // isDisconnecting
            isDisconnecting = true;

            if (!preparingForReconnect) {
              // move cancelReconnect above this synchronized block fix for bug 35202
              if (reconnectDS != null) {
                // break recursion
                if (isDebugEnabled) {
                  logger.debug("disconnecting reconnected DS: {}", reconnectDS);
                }
                InternalDistributedSystem r = reconnectDS;
                reconnectDS = null;
                r.disconnect(false, null, false);
              }
            } // !reconnect
          } // synchronized (this)
        } // synchronized (GemFireCache.class)

        securityService.close();

        if (!isShutdownHook) {
          shutdownListeners = doDisconnects(attemptingToReconnect);
        }

        if (!attemptingToReconnect) {
          alertingSession.stopSession();
        }

      } finally { // be ABSOLUTELY CERTAIN that dm closed
        try {
          // Do the bulk of the close...
          dm.close();
          // we close the locator after the DM so that when split-brain detection
          // is enabled, loss of the locator doesn't cause the DM to croak
          if (startedLocator != null) {
            startedLocator.stop(forcedDisconnect, preparingForReconnect, true);
            startedLocator = null;
          }
        } finally { // timer canceled
          // bug 38501: this has to happen *after*
          // the DM is closed :-(
          if (!preparingForReconnect) {
            SystemTimer.cancelTimers(this);
          }
        } // finally timer cancelled
      } // finally dm closed

      if (!isShutdownHook) {
        doShutdownListeners(shutdownListeners);
      }

      functionStatsManager.close();
      metricsService.stop();

      InternalFunctionService.unregisterAllFunctions();

      if (sampler != null) {
        sampler.stop();
        sampler = null;
      }

      if (!attemptingToReconnect) {
        loggingSession.stopSession();
      }

      EventID.unsetDS();

    } finally {
      try {
        if (getOffHeapStore() != null) {
          getOffHeapStore().close();
        }
      } finally {
        try {
          removeSystem(this);
          if (!attemptingToReconnect) {
            loggingSession.shutdown();
            SocketCreatorFactory.close();
          }
          alertingService.useAlertMessaging(new NullAlertMessaging());
          clusterAlertMessaging.get().close();
          alertingSession.shutdown();
          // Close the config object
          config.close();
        } finally {
          // Finally, mark ourselves as disconnected
          setDisconnected();
          SystemFailure.stopThreads();
        }
      }
    }
  }
Disconnects this VM from the distributed system. Shuts down the distribution manager.

@param preparingForReconnect true if called by a reconnect operation
@param reason the reason the disconnect is being performed
@param keepAlive true if user requested durable subscriptions are to be retained at server.
geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java