我有一个管理/缓存大型数据对象的系统。我想确保当它加载下一个对象时,有足够的内存空间。
我可能会误解以下概念,但这就是我挣扎的地方:
java.lang.Runtime.getRuntime().freeMemory()
,因为它不计算可以释放的内存,也就是说这个值有时会比我可能使用的内存量小得多。maxMemory()
和 totalMemory()
的理解是它们通常比我可以分配的要大,因为它们计算程序已经占用的内存。另外,后者与 JVM 发行版无关,这在我的环境中是不可接受的。gc()
,然后使用 freeMemory()
获得更准确的值,但这会占用太多 CPU 时间并使服务器过载。此外,这种方法被认为是一种不好的做法。如有错误请指出。我觉得当您有一系列大型对象要缓存在不同的池/级别等中时,这是一个相当常见的场景。我想知道是否有一个通用的解决方案或现有的库可以做到这一点。
我想你可以手动跟踪可用内存:如果你知道如何估计缓存条目的大小,并且可以确保它在失效后可用于垃圾回收,因为你控制客户端代码,你可以使用一个简单的计数器 -可用字节数。
请参阅下面的伪代码片段作为示例。显然,代码片段中内存泄漏的可能性很大,您必须考虑并发访问等;它只是说明了这个想法。
class MemoryReservingCache<K, V> {
// Total memory available for all caches. The initial value can be
// calculated based on the heap size.
static long freeSizeBytes;
Map<K,V> storage;
// Ideally, the client code should call reserve before
// allocating objects.
boolean reserve(long bytes) {
if (freeSizeBytes < bytes) {
return false;
}
else {
freeSizeBytes -= bytes;
return true;
}
}
void put(K key, V value) {
storage.put(key, value);
}
V get(K key) {
return storage.get(key);
}
void invalidate(K key) {
// If there is an automatic eviction process, you may try to
// notify the client code to synchronously make entries that
// being evicted available for garbage collection.
storage.remove(key);
}
void free(long bytes) {
freeSizeBytes += bytes;
}
}
// Estimate the size of the (key, value) pair.
// For example, read it from some metadata.
long requiredBytes = ...;
if (!cache.reserve(requiredBytes)) {
// Out of memory.
}
K key = ...;
V value = ...;
cache.put(key, value);
// Clear *all* references to both value and key to make sure that
// they are *available* for garbage collection if memory is needed
// for other objects.
value = null;
cache.invalidate(key);
key = null;
// Although the requiredBytes may still be unavailable according to
// System.freeMemory() they *are* available sort of on demand.
cache.free(requiredBytes)