Android Runtime.getRuntime().freeMemory()会返回0吗?

胡嘉歆
2023-12-01

背景

上周基于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。

 类似资料: