【问题标题】:How to override handleUncaughtException without changing its functionallity如何在不更改其功能的情况下覆盖处理未捕获的异常
【发布时间】:2018-01-06 05:16:26
【问题描述】:

我在Stackoverflow 上问过this 问题,答案对我有用,它覆盖handleUncaughtException,我保存异常并抛出默认Unfortunately app has stopped working,但是当我将它集成到我的应用程序中时,我面临一个问题。

这就是我得到的答案。

private Thread.UncaughtExceptionHandler defaultExceptionHandler;

    public void registerCrash(){
        defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
            @Override
            public void uncaughtException (Thread thread, Throwable e){
                handleUncaughtException (thread, e);
                if(defaultExceptionHandler != null){
                    defaultExceptionHandler.uncaughtException(thread, e);
                }
            }
        });
    } 

它是做什么的,首先它转到handleUncaughtException (thread, e);我在这个方法中保存崩溃日志,然后它读取这一行

 if(defaultExceptionHandler != null){
    defaultExceptionHandler.uncaughtException(thread, e);
}

这里我们再次抛出未捕获的异常,所以它再次进入第一行,再次保存异常,然后进入循环,应用程序没有响应。

我想要的是保存崩溃日志,然后向用户显示默认的Unfortunate 消息。

编辑

在应用程序启动时,它会显示此内容;

defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

当应用程序崩溃时,它会读取这些行

Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
    @Override
    public void uncaughtException (Thread thread, Throwable e){

        handleUncaughtException (thread, e); //Custom Method 

        if(defaultExceptionHandler != null){
            defaultExceptionHandler.uncaughtException(thread, e);
        }
    }

所以它首先转到handleUncaughtException(),我提供了自定义实现,然后转到此;

if(defaultExceptionHandler != null){
  defaultExceptionHandler.uncaughtException(thread, e);
}

defaultExceptionHandler 永远不会为空;所以它会在多次崩溃的情况下进入循环。

我尝试在那里添加count,但每次都是0

【问题讨论】:

  • So it goes in a loop in case of multiple crashes 你能指出发生这种情况的场景吗?是什么导致另一个异常发生?
  • @azizbekian :我无法找到重现它的步骤。这种情况并非每次都会发生,但有时会发生
  • 什么是 defaultExceptionHandler 方法。是你自己的方法吗?如果是,请发布该方法代码。并发布handleUncaughtException(thread, e)方法代码
  • 你有堆栈跟踪要发布吗? defaultExceptionHandler.uncaughtException 会做 system.exit 吗?它可能会引发安全异常
  • “在应用程序启动时它读取这个”是什么意思? (你在哪里做的)

标签: android performance android-fragments exception-handling


【解决方案1】:

最可能的解释是您的registerCrash() 方法被调用了两次。

第一次注册Handler 1;此时没有默认处理程序,因此它将defaultExceptionHandler 设置为null。第二次,您注册Handler 2,然后更新defaultExceptionHandler 以指向Handler 1

在未捕获的异常中,Handler 2 首先被调用。它调用您的自定义处理程序方法,然后调用 defaultExceptionHandler,它现在指向 Handler 1

Handler 1 被调用。它第二次调用您的自定义处理程序方法,然后调用defaultExceptionHandler现在指向它自己。重复此步骤,直到您的堆栈溢出。

我建议进行两项更改。首先,添加一个守卫以确保您只注册一次崩溃处理程序。其次,不要将回退处理程序存储在字段中;在闭包中捕获它,因此您的处理程序看到的值永远不会改变。

private static final AtomicBoolean CRASH_HANDLER_REGISTERED = new AtomicBoolean();

public void registerCrash() {
    if (CRASH_HANDLER_REGISTERED.compareAndSet(false, true)) {
        final Thread.UncaughtExceptionHandler defaultHandler =
            Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler(
            new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread thread, Throwable e) {
                    handleUncaughtException(thread, e); // Custom Method

                    if (defaultHandler != null) {
                        defaultHandler.uncaughtException(thread, e);
                    }
                }
            }
        );
    }
}

【讨论】:

    【解决方案2】:

    我建议你尝试另一种方法,避免覆盖异常,捕获它并检索错误代码,然后这样做:

    when x code with x conditions verify, do that

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      相关资源
      最近更新 更多