在 Java 中检测低内存?

Detect low memory in Java?

为了防止 OutOfMemoryError 我想创建一个代码来清除我程序中的一些缓存,当存在超出可用 RAM 的危险时。

当内存处于最大可用内存的特定百分比时,我如何从代码内部检测到内存并能够做出反应?

检测 Java 中的内存消耗以对您的代码做出反应不是一个好主意。您永远不知道垃圾收集器的行为方式、启动时间、启动频率、可以释放多少内存……

如果要防止对对象的引用阻止垃圾收集器将其删除,则可以使用弱引用 (java.lang.ref)。但是,如果您实施缓存,这可能会使缓存变得无用,因为您的缓存对象可能会被非常快速且频繁地删除。

我建议使用 LRU-Cache。这样的缓存是有一定容量的。如果超过此容量,最近最少使用的元素将被踢出缓存。这以一种简单的方式防止了缓存可以无限增长。

如果你 google 可以找到一些简单的实现:

public class LRUMap<K, V>  extends LinkedHashMap<K, V> {
    private static final long serialVersionUID = 1L;
    private final int capacity;

    public LRUMap(final int capacity) {
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > capacity;
    }
}

如果您需要更多,我会检查现有的缓存实现。它们可能支持额外的配置功能,例如 e. G. 缓存条目的最长期限。

事实证明(令我惊讶的是!)有一种半可靠的方法来检测超过预设阈值的内存使用情况。

MemoryPoolMXBean class 提供了一种方法来设置内存池的使用阈值,并在池的使用超过阈值时收到通知。

您可以通过调用 ManagementFactory.getMemoryPoolMXBeans().

获取 JVM 的内存 MXBean 实例

有两种阈值,您需要了解它们之间的区别才能正确使用它们。比较复杂:参考javadoc

还应该注意的是规格:

  • 说不是所有的space都支持阈值检查,
  • 表示在测试阈值交叉时没有限制:

    "A Java virtual machine performs usage threshold crossing checking on a memory pool basis at its best appropriate time ..."

  • 说明如何测试是否支持阈值检查,以及如何注册通知。