正确认识 Error 和 OOM
首先,这里 catch 的是一个 Error,原则上,触发了 Error 时,它的执行状态已经无法恢复了,此时需要终止线程甚至是终止虚拟机。这是一种不应该被我们应用层去捕获的异常。具体可以参见之前的文章《Java 异常捕获》。
然后还要理清楚,OOM 是如何产生的。
其实 OOM 产生的原因有很多,例如申请了大段的内存,虚拟内存不足等等,这些原因都可能引发 OOM。大多数时候,OOM 触发的时候,都只是压死骆驼的最后一根稻草,也许就是正常的内存申请,但是已经没有更多的内存可以使用了,此时就引发 OOM。
例如上面这种 OOM,其实就是开启了一个新页面,在页面的布局中加载了一个本地资源,最终触发 OOM 了。
catch OOM 的先决条件
想通过 try-catch 避免 OOM,你需要两个先决条件:
触发 OOM 的代码是开发者可控的。
在 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,导致崩溃。
网友评论