void setEvictionThreshold(final float evictionThreshold) {
    hasEvictionThreshold = true;

    synchronized (this) {
      // If the threshold isn't changing then don't do anything.
      if (evictionThreshold == thresholds.getEvictionThreshold()) {
        return;
      }

      // Do some basic sanity checking on the new threshold
      if (evictionThreshold > 100.0f || evictionThreshold < 0.0f) {
        throw new IllegalArgumentException(
            "Eviction percentage must be greater than 0.0 and less than or equal to 100.0.");
      }
      if (getTenuredMemoryPoolMXBean() == null) {
        throw new IllegalStateException(
            String.format("No tenured pools found.  Known pools are: %s",
                getAllMemoryPoolNames()));
      }
      if (evictionThreshold != 0 && thresholds.isCriticalThresholdEnabled()
          && evictionThreshold >= thresholds.getCriticalThreshold()) {
        throw new IllegalArgumentException(
            "Eviction percentage must be less than the critical percentage.");
      }

      thresholds = new MemoryThresholds(thresholds.getMaxMemoryBytes(),
          thresholds.getCriticalThreshold(), evictionThreshold);

      updateStateAndSendEvent();

      // Start or stop monitoring based upon whether a threshold has been set
      if (thresholds.isEvictionThresholdEnabled()
          || thresholds.isCriticalThresholdEnabled()) {
        startMonitoring();
      } else if (!thresholds.isEvictionThresholdEnabled()
          && !thresholds.isCriticalThresholdEnabled()) {
        stopMonitoring();
      }

      stats.changeEvictionThreshold(thresholds.getEvictionThresholdBytes());
    }
  }
Start a separate thread for polling the JVM for heap memory usage.
geode-core/src/main/java/org/apache/geode/internal/cache/control/HeapMemoryMonitor.java