前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android中关于OOM的捕获的方法

Android中关于OOM的捕获的方法

作者头像
Vaccae
发布2022-04-06 20:54:59
7160
发布2022-04-06 20:54:59
举报
文章被收录于专栏:微卡智享微卡智享

前言

做Android开发其实经常会遇到OOM然后程序崩溃的情况,导致这种情况一般来说是内存泄露造成的,捕获内存泄露的工具是leakCanary2还是推荐一下,当然本章并不是说这个的使用方法,程序OOM时会造成直接崩溃,在使用中会影响用户体验,这里就说一下实现OOM的捕获的方法。

实现效果

捕获OOM

结论

将try catch(e:Exception)改为try catch(e:Throwable)即可实现捕获OOM

为什么改为Throwable后就能捕获OOM了呢?那我们做个小小的Demo来测试一下。

Demo测试

任何一个Project中新一个文件,我这起名为Test

为了程序运行中能够更快的出现OOM,要改一下配置,主要就是把JVM的内存堆分配的小一点,

  1. 打开Run选项中选择Edit Configurations

2.将刚才创建的Test.kt的文件中VM options项里填上-Xms20m -Xmx20m

参数项的说明:

  • -Xms20m (JVM初始分配的堆内存)
  • -Xmx20m(最大可使用内存)
  • -XX:+HeapDumpOnOutOfMemoryError(r,JVM会在遇到OutOfMemoryError时拍摄一个“堆转储快照”)(可以不设置,对造成OOM没有帮助)

Test的完整代码

代码语言:javascript
复制
package pers.vaccae.draganddropdemo

fun main(){
    class oomobj{
        var testno =1
        var testname ="11234"
    }
    val list = mutableListOf<oomobj>()

    try {
        while (true){
            list.add(oomobj())
        }
    } catch (e: Exception) {
        print(e.message.toString())
    }
}

从上面代码中可以看到,有个oomobj的类,然后通过while的死循环不停的在集合中插入新的oomobj这个类,用try catch(e:Exception)进行捕获,得到下图:

可以看到,提了OutOfMemoryError,那我们点一下OutOfMemoryError这里

可以看出来OutOfMemoryError继承自VirtualMachineError类。那为什么Exception捕获不到呢?接下来再看一个图:

从上图中可以看出来,OutOfMemory继承的VirtualMachineError是Error的分支里,而我们用Exception中是无法捕获的,想到获取到Error的信息,可以从它们的父类Throwable中获取,接下来我们改一下代码,将Exception改为Throwable

改完后可以正常打印Throwable的输出结果

Throwable后处理

虽然我们捕获了OOM,但如果内存就是溢出后,那程序是否还能运行了呢?那我们改一下代码再看看

代码语言:javascript
复制
package pers.vaccae.draganddropdemo

fun main(){
    class oomobj{
        var testno =1
        var testname ="11234"
    }

    val list = mutableListOf<oomobj>()

    try {
        while (true){
            list.add(oomobj())
        }
    } catch (e: Throwable) {
        println(e.message.toString())
        list.clear()
        println("list清空")
    }
    
    try {
        println("list重新进入循环")
        while (true){
            list.add(oomobj())
        }
    } catch (e: Throwable) {
        println(e.message.toString())
    }
}

在catch后将list清空,再次进入循环,看看下图的结果:

从输出的结果上可以看到,进入异常处理后,我们将List清空的,还会继续向下执行,当遇到第二次OOM时又会捕获到输出。

JDK中Error类的的注释(如下)里提到过,Error是一种严重的问题,应用程序不应该捕捉它。所以说捕获OOM只是一个治标的办法,其实最核心的还是要解决内存泄露的问题。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微卡智享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 捕获OOM
    • 结论
      • Demo测试
      • Test的完整代码
        • Throwable后处理
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档