为了防止OutOfMemoryError
我想创建一个代码,当存在可用RAM的危险时,清除程序中的一些缓存。
当内存距离可用的最大值有一定百分比时,我如何从代码内部检测到并能够做出反应?
答案 0 :(得分:1)
检测Java中的内存消耗以对代码做出反应并不是一个好主意。你永远不知道垃圾收集器的行为方式,启动时的频率,以及它可以释放多少内存,...
如果要防止对对象的引用阻止垃圾收集器将其删除,则可以使用WeakReference(java.lang.ref)。但是如果你实现了一个缓存,这可能会使缓存变得无用,因为你的缓存对象可能会被非常快速地删除。
我建议使用LRU-Cache。这样的缓存具有一定的容量。如果超出此容量,则最近最少使用的元素将从缓存中踢出。这可以简单地防止缓存无限增长。
如果你谷歌的话,你可以找到一些简单的实现:
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.您缓存条目的最长年龄。
答案 1 :(得分:0)
事实证明(令我惊讶的是)有一种半可靠的方法来检测超过预设阈值的内存使用情况。
MemoryPoolMXBean
类提供了一种在内存池上设置使用率阈值的方法,并在池的使用率超过阈值时收到通知。
您可以通过调用ManagementFactory.getMemoryPoolMXBeans()
来获取JVM的内存MXBean实例。
有两种阈值,您需要了解它们之间的区别才能正确使用它们。这很复杂:请参考javadoc。
还应该注意规范:
表示测试阈值交叉的时间没有限制:
“Java虚拟机在最合适的时间基于内存池执行使用阈值交叉检查...”
解释了如何测试是否支持阈值检查,以及如何注册通知。