private static void runProctor() {
    // Note that the javadocs say this can return Long.MAX_VALUE.
    final long maxMemory = Runtime.getRuntime().maxMemory();

    // Allocate this error in advance, since it's too late once it's been detected!
    final OutOfMemoryError oome = new OutOfMemoryError(
        String.format(
            "%s : memory has remained chronically below %s bytes (out of a maximum of %s ) for %s sec.",
            PROCTOR_NAME, minimumMemoryThreshold, maxMemory, WATCHDOG_WAIT));

    logFine(PROCTOR_NAME,
        "Starting, threshold = " + minimumMemoryThreshold + "; max = " + maxMemory);
    while (!isCacheClosing) {
      if (stopping) {
        return;
      }

      try {
        try {
          Thread.sleep(MEMORY_POLL_INTERVAL * 1000);
        } catch (InterruptedException e) {
          // ignore
        }

        if (stopping) {
          return;
        }

        if (failureActionCompleted) {
          return;
        }
        if (failure != null) {
          notifyWatchDog();
          logFine(PROCTOR_NAME, "Failure has been reported, exiting");
          return;
        }

        if (!MONITOR_MEMORY) {
          continue;
        }

        long totalMemory = Runtime.getRuntime().totalMemory();
        if (totalMemory < maxMemory) {
          if (DEBUG) {
            logFine(PROCTOR_NAME,
                "totalMemory (" + totalMemory + ") < maxMemory (" + maxMemory + ")");
          }
          firstStarveTime = NEVER_STARVED;
          continue;
        }
        if (lastTotalMemory < totalMemory) {
          lastTotalMemory = totalMemory;
          firstStarveTime = NEVER_STARVED;
          continue;
        }
        lastTotalMemory = totalMemory;

        long freeMemory = Runtime.getRuntime().freeMemory();
        if (freeMemory == 0) {
          // This is to workaround X bug #41821 in JRockit. Often, Jrockit returns 0 from
          // Runtime.getRuntime().freeMemory() Allocating this one object and calling again seems to
          // workaround the problem.
          new Object();
          freeMemory = Runtime.getRuntime().freeMemory();
        }
        // Grab the threshold and starve time once, under mutex, because
        // it's publicly modifiable.
        long curThreshold;
        long lastStarveTime;
        synchronized (memorySync) {
          curThreshold = minimumMemoryThreshold;
          lastStarveTime = firstStarveTime;
        }

        if (freeMemory >= curThreshold || curThreshold == 0) {
          // Memory is FINE, reset everything
          if (DEBUG) {
            logFine(PROCTOR_NAME, "Current free memory is: " + freeMemory);
          }

          if (lastStarveTime != NEVER_STARVED) {
            logFine(PROCTOR_NAME, "...low memory has self-corrected.");
          }
          synchronized (memorySync) {
            firstStarveTime = NEVER_STARVED;
          }
          continue;
        }

        // Memory is low
        long now = System.currentTimeMillis();
        if (lastStarveTime == NEVER_STARVED) {
          if (DEBUG) {
            logFine(PROCTOR_NAME,
                "Noting current memory " + freeMemory + " is less than threshold " + curThreshold);
          } else {
            logWarning(PROCTOR_NAME,
                "Noting that current memory available is less than the currently designated threshold",
                null);
          }

          synchronized (memorySync) {
            firstStarveTime = now;
          }
          System.gc(); // Attempt to free memory and avoid overflow
          continue;
        }

        if (now - lastStarveTime < MEMORY_MAX_WAIT * 1000) {
          if (DEBUG) {
            logFine(PROCTOR_NAME, "...memory is still below threshold: " + freeMemory);
          } else {
            logWarning(PROCTOR_NAME,
                "Noting that current memory available is still below currently designated threshold",
                null);

          }
          continue;
        }

        logWarning(PROCTOR_NAME, "Memory is chronically low; setting failure!", null);
        SystemFailure.setFailure(oome);
        notifyWatchDog();
        return;
      } catch (Throwable t) {
        logWarning(PROCTOR_NAME, "thread encountered a problem", t);
      }
    }
  }
This is the run loop for the proctor thread
geode-core/src/main/java/org/apache/geode/SystemFailure.java