private void forceLowMemory() {
      long maxMem = Runtime.getRuntime().maxMemory();
      long avail = Runtime.getRuntime().freeMemory();
      long thresh = (long) (avail * 0.40);
      long ferSure = (long) (avail * 0.30);
      SystemFailure.setFailureMemoryThreshold(thresh);
      SystemFailure.setFailureAction(() -> {
        peskyMemory = null;
        System.gc();
        synchronized (SystemFailure.class) {
          SystemFailure.class.notify();
        }
      });

      peskyMemory = new ArrayList();
      // Allocate this _before_ exhausting memory :-)
      final AssertionError whoops = new AssertionError("Timeout!");

      // Fill up a lot of memory
      for (;;) {
        peskyMemory.add(new long[100000]);
        if (Runtime.getRuntime().totalMemory() < maxMem) {
          continue; // haven't finished allocating max allowed
        }
        if (Runtime.getRuntime().freeMemory() < ferSure) {
          break;
        }
      } // for


      // Wait for the failure monitor to kick in
      long fin = System.currentTimeMillis() + (long) (SystemFailure.MEMORY_MAX_WAIT * 1.5 * 1000);
      for (;;) {
        long now = System.currentTimeMillis();
        if (now > fin) {
          throw whoops;
        }
        synchronized (SystemFailure.class) {
          try {
            if (peskyMemory == null) {
              break;
            }
            SystemFailure.class.wait(fin - now);
          } catch (InterruptedException e) {
            fail("interrupted");
          }
        } // synchronized
        if (peskyMemory == null) {
          break;
        }
      } // for
    }
Allocate objects until we are chronically low, but don't generate OutOfMemoryError
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/SystemFailureDUnitTest.java