Android 关于内存溢出的一些误会

1 篇文章 0 订阅

从哪些情况导致内存溢出说起

说到Android的内存溢出,一般人都会说到以下几点

  • 内存泄漏
  • 不用的图片没有GC
  • 大图加载
  • 加载大量的图片
  • 创建大量的线程

那么真的是这样吗?是不是我不加载大图就不会内存溢出?是不是我不加载大量图片就不会内存溢出?不创建大量线程就不会内存溢出?…

答案是否定的。

不信你试试下面这个代码。

List<String> list = new ArrayList<>();

private void doTest() {
    for (int i=0;;i++){
        Log.e("TAG", "doTest: "+i );
        list.add(i+"");
    }
}

楼主的小米8 内存会一直暴涨到1g多,然后虽然没有崩溃,但是log里会输出。

2019-12-30 19:03:51.576 30046-30057/com.lzp.appexp E/System: Uncaught exception thrown by finalizer
2019-12-30 19:04:37.275 30046-30057/com.lzp.appexp E/System: java.lang.OutOfMemoryError: Failed to allocate a 8 byte allocation with 0 free bytes and 0B until OOM, max allowed footprint 536870912, growth limit 536870912

很明显我也没有创建大图,甚至都没有加载图片。也没有创建线程。

我们再来分析下为什么会发生这种情况。

看过内存JVM回收机制和内存回收算法发应该都知道,JVM所管理的内存主要包括以下几个运行时数据区域:方法区,本地方法区,堆,虚拟机栈,程序计数器。其中,程序计数器,虚拟机栈,本地方法区都是随性线程而生,随线程而灭的。堆和方法区会使用可达性分析,计数法等等算法,进行垃圾回收。显然例子的每个字符串都不能回收。那么内存也就会持续增加。直到oom。

再问哪些情况会导致内存溢出

再来看看题目开始的问题,哪些情况会导致内存溢出呢?

显然答案是任何对象的创建都有可能导致内存溢出。但是有几个场景会加大内存溢出的概率。比如:

  • 内存泄漏
  • 不用的图片没有GC
  • 大图加载
  • 加载大量的图片
  • 创建大量的线程

就是开头我们提到的那些了。

我们该怎么避免内存溢出

既然知道了什么情况会产生内存溢出。要解决也就不难了。总结如下

  • 创建对象的时候,不要创建大对象。比如创建bitmap的时候指定宽高,可以大幅度减少内存的消耗。
  • 创建了大对象要及时回收。或者大对象标记为可以被回收的,比如软引用,虚引用,弱引用等等。
  • 创建对象的时候考虑下回收时机。比如能在局部变量,不声明成员变量,能成员不静态。这样就能减少GC的次数。
  • 避免频繁的创建对象,比如在for循环里,onDraw里,创建对象。会被频繁的调用,容易内存抖动。
  • …(你来补充)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值