OutOfMemoryError 可以被 try catch 吗 ?

OutOfMemoryError 可以被 try catch 吗?

注意看下面的 Gif,每点击一次 Allocate 20MB ,都会给数组容量增加 20*1024*1024,当然应该并不是 20 MB。如下面代码所示:

binding.allocate.setOnClickListener {
 try {
  bytes = ByteArray(bytes.size + 1024 * 1024 * 20)
  refreshMemory()
 } catch (e: OutOfMemoryError) {
  binding.oomError.text = "Catch OOM : \n ${e.message}"
 }
}

 

 

当点击第 7 次时,发生了 OutOfMemoryError ,并且 catch 代码块执行了。

Catch OOM :  Failed to allocate a 146801680 byte allocation with 25165824 free bytes and 133MB until OOM, target footprint 153948888, growth limit 268435456

所以,OutOfMemoryError 是可以 try catch 的。

顺道画了一个思维导图回顾一下 Java 的异常体系。

 

上面的图片没有罗列出所有的异常类型,但也基本概括了 Java 异常的继承体系。所有的异常类都继承自 Throwable ,Throwable 有两个直接子类 Error 和 Exception 。

Exception 一般指可以/应该捕获和处理的异常。

它的两个直接子类 IOException 和 RuntimeException 及其子类都是我们在代码中经常遇到的一些错误。

RuntimeException 是在程序运行中可能发生的异常,我们可以不捕获它,但可能带来 Crash 的代价,但是过多的捕获异常又不利于暴露和调试异常情况。

在开发过程中,我们更多的应该及时暴露问题。除了 RuntimeException 以外,其他异常可以统称为 非运行时异常 或者 受检异常,这些异常必须被捕获,否则编译期就会报错。

Error 一般指非正常状态的,比较严重的,不应该被捕获的系统错误。

再回头看看 OutOfMemoryError 的父类们,

OutOfMemoryError <- VirtualMachineError <- Error

OutOfMemoryError 是一个 Error ,Error 不应该被捕获。

那么,捕获 OutOfMemoryError 有什么意义呢?

捕获 OutOfMemoryError 有什么意义?

一般情况下并没有什么太大意义,相信你在开发中也几乎没有写过 catch OOM 的代码。

 

如果你把捕获 OOM 当做处理 OOM 的一种手段,无疑是不合适的。

 

你无法保证你 catch 的代码就是导致 OOM 的原因,可能它只是压死骆驼的最后一根稻草,甚至你也无法保证你的 catch 代码块中不会再次触发 OOM 。

 

我也从来没有写过捕获 OOM 的代码,但无意中在 Android 源码中发现了这样的操作。在 View.java 的 buildDrawingCacheImpl() 方法中有这么一段代码:

 

try {
    bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
                        width, height, quality);
    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
    if (autoScale) {
        mDrawingCache = bitmap;
     } else {
         mUnscaledDrawingCache = bitmap;
     }
     if (opaque && use32BitCache) bitmap.setHasAlpha(false);
} catch (OutOfMemoryError e) {
    // If there is not enough memory to create the bitmap cache, just
    // ignore the issue as bitmap caches are not required to draw the
    // view hierarchy
    if (autoScale) {
        mDrawingCache = null;
    } else {
        mUnscaledDrawingCache = null;
}
mCachingFailed = true;
......
buildDrawingCacheImpl() 方法的大致作用是为当前 View 生成一个 Bitmap 缓存。

在构建 Bitmap 对象的时候,如果捕捉到了 OOM ,就放弃生成 Bitmap 缓存,因为在 View 的绘制过程中 Bitmap Cache 并不是必须存在的。所以在这里没有必要抛出 OOM ,而是自己捕获就可以了。

转载:https://mp.weixin.qq.com/s/PFkKR1KpIm7wc2ZiKsm63A

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值