private static AppMemoryUsage calculateMemoryUsage() {
    MemoryUsage heapMemoryUsage = MEMORY_MX_BEAN.getHeapMemoryUsage();

    long directBuffersUsedByFileCacheBytes = DirectByteBufferAllocator.ALLOCATOR.getStatistics().totalSizeOfBuffersAllocatedInBytes;
    //RC: counter-intuitively, but memoryMXBean.getNonHeapMemoryUsage() does NOT count direct ByteBuffers.
    //    nonHeapMemoryUsage is mostly about JVM-internal data structures -- code cache, metaspace, etc.
    //    Direct ByteBuffers (seems to be) invisible to any public API, so we need some private API for it
    long directBuffersUsedBytes = IOUtil.directBuffersTotalAllocatedSize();
    if (directBuffersUsedBytes <= 0) {
      //can't get value by some reason => use directBuffersUsedByFileCacheBytes as lower bound, better than nothing:
      directBuffersUsedBytes = directBuffersUsedByFileCacheBytes;
    }

    //RC: I know no way to get thread-stack size, but 1Mb seems to be a default stack size for most OSes, so
    //    lets just assume (1 thread = 1Mb of stack). This seems to be an underestimation: seems like JVM
    //    provision memory for threads with big margin, and also thread local allocation 'arenas' are not included
    long threadsStackBytes = THREAD_MX_BEAN.getThreadCount() * (long)IOUtil.MiB;

    //pools list could change during execution, so can't be cached once
    long jvmInternalsMemoryBytes = jvmInternalsMemory(ManagementFactory.getMemoryPoolMXBeans());

    long memoryMappedFilesBytes = MMappedFileStorage.totalBytesMapped();

    return new AppMemoryUsage(
      heapMemoryUsage.getMax(), heapMemoryUsage.getCommitted(), heapMemoryUsage.getUsed(),
      jvmInternalsMemoryBytes,
      directBuffersUsedBytes, directBuffersUsedByFileCacheBytes,
      threadsStackBytes,
      memoryMappedFilesBytes
    );
  }
private static AppMemoryUsage calculateMemoryUsage()