背景
上周基于LruCache实现了一个缓存,实现逻辑大概如下:
//使用剩余内存的1/16作为缓存池的最大值
int size = Runtime.getRuntime().freeMemory() / 16;
LruCache<String, String> myCache = new LruCache<String, String>(cacheSize) {
protected int sizeOf(String key, String value) {
//自定义size计算方式
....
}
};
以上写法和官方文档Caching Bitmaps类似,区别在于官方文档用的是Runtime.getRuntime().maxMemory(),Runtime.getRuntime().maxMemory()意思虚拟机计划使用的最大内存,freeMemory()意思是当前已开辟内存中的剩余部分。似乎freeMemory()比maxMemory()在内存使用上更加保险,就这样用了,但是上述 代码发布到线上却概率性抛出了IllegalArgumentException,原因是初始化传入的cacheSize小于等于0。
Runtime.getRuntime().freeMemory()会返回0吗?
从API文档看,没有这方面的说明,从意义上看,貌似可能会。但是还是想从源码上佐证一下。
Runtime.getRuntime().freeMemory()具体源码是在Native中实现,具体对应的Native代码在,platform/runtime/gc/heap.h。
// Returns how much free memory we have until we need to grow the heap to perform an allocation.
// Similar to GetFreeMemoryUntilGC. Implements java.lang.Runtime.freeMemory.
size_t GetFreeMemory() const {
size_t byte_allocated = num_bytes_allocated_.load(std::memory_order_seq_cst);
size_t total_memory = GetTotalMemory();
// Make sure we don't get a negative number.
return total_memory - std::min(total_memory, byte_allocated);
}
从代码看,如果byte_allocated大于等于total_memory,那么的确是返回了0。
那么Runtime.getRuntime().maxMemory()呢?
// Implements java.lang.Runtime.maxMemory, returning the maximum amount of memory a program can
// consume. For a regular VM this would relate to the -Xmx option and would return -1 if no Xmx
// were specified. Android apps start with a growth limit (small heap size) which is
// cleared/extended for large apps.
size_t GetMaxMemory() const {
// There is some race conditions in the allocation code that can cause bytes allocated to
// become larger than growth_limit_ in rare cases.
return std::max(GetBytesAllocated(), growth_limit_);
}
Runtime.getRuntime().maxMemory()至少返回的是growth_limit_,这个值是在APP初始化时被赋值的,因此这里返回结果必然大于0。