catch 住 OOM,行吗?

try {
    var byte = ByteArray(10000000 * 1024 * 1024)
} catch (ignore: OutOfMemoryError) {

}

正确认识 Error 和 OOM

首先,这里 catch 的是一个 Error,原则上,触发了 Error 时,它的执行状态已经无法恢复了,此时需要终止线程甚至是终止虚拟机。这是一种不应该被我们应用层去捕获的异常。具体可以参见之前的文章《Java 异常捕获》。

然后还要理清楚,OOM 是如何产生的。

其实 OOM 产生的原因有很多,例如申请了大段的内存,虚拟内存不足等等,这些原因都可能引发 OOM。大多数时候,OOM 触发的时候,都只是压死骆驼的最后一根稻草,也许就是正常的内存申请,但是已经没有更多的内存可以使用了,此时就引发 OOM。

例如上面这种 OOM,其实就是开启了一个新页面,在页面的布局中加载了一个本地资源,最终触发 OOM 了。

catch OOM 的先决条件

想通过 try-catch 避免 OOM,你需要两个先决条件:

  1. 触发 OOM 的代码是开发者可控的。

  2. 在 try 块中,申明对象并会申请了大段内存,导致触发 OOM。

只有满足这两个条件,你才可以说,你对 OOM 有控制权,能够将其 catch 住。

在一些开源库中,其实就已经在使用这种方法。例如 Volley 中,ImageRequest 中,就有这样一段代码。

在处理图片的时候,如果遇见 OOM,就放弃掉,同时把错误抛出去。

应该 catch 住 OOM 吗?

就像前面说过,触发了 Error 时,它的执行状态已经无法恢复了,此时需要终止线程甚至是终止虚拟机。这是一种不应该被我们应用层去捕获的异常。

理论上我们不应该去主动 catch OOM。哪怕在此处 catch 住了,可 App 当前的状态也已经处于“濒危”状态。如果不采取措施,此时不崩,换一个地方也会崩,逃的了初一,逃不过十五。

正确的做法是,主动去管理内存。图片是吃内存的大户,而如果 App 内统一了图片加载库,例如 Glide,在内存吃紧的时候,就可以通过 Glide 主动释放掉一些内存,让 App 恢复到健康的状态。

小结时刻

OOM 能不能被 catch 住?在某些条件下可以。仅在我们可控的代码,并且在 try 块中存在申请大量内存的情况下,此时触发的 OOM,才是可以被 catch 住的。

当我们 catch 住 OOM 的时候,我们应该主动释放一些我们可控的内存,做好内存管理,避免在后续的操作中,立即又会触发 OOM,导致崩溃。

本文对你有帮助吗?留言、好看、转发是最大的支持,谢谢!

Refrence:

https://www.zhihu.com/question/54630917


联机圆桌」????推荐我的知识星球,一年 50 个优质问题,上桌联机学习。

公众号后台回复成长『成长』,将会得到我准备的学习资料,也能回复『加群』,一起学习进步;你还能回复『提问』,向我发起提问。

推荐阅读:

关于字符编码,你需要知道的都在这里 | 图解:HTTP 范围请求 | Java 异常处理 | 安卓防止用户关闭动画导致动画失效 | Git 找回遗失的代码 | 阿里的 Alpha 助力 App 启动速度优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值