Eclipse - 当Android应用程序上引发未处理的异常时,中断用户代码

2022-09-02 22:39:20

我的问题很简单:

  • 我使用Ecplise(Luna或Neon)在Android上开发,我不想使用Android Studio。

  • 我希望仅在导致异常的堆栈的最后一次用户代码调用上调试所有未处理的异常的中断(因此,例如,当由于将空引用传递给本机Android SDK方法而导致的异常时,我不想中断无用的ZygonteInit&MethodAndArgsCaller.run()。

我知道我可以在断点视图中为特定异常设置断点(NullPointerException..可投掷...)但我想打破所有未处理。我知道我可以通过在Java调试选项中设置“步骤过滤器”来过滤调试,但在我的情况下,这并不适用于所有异常。

编辑

在下图中,当引发异常时,我在调试视图中的堆栈(在我的代码中被零除)

enter image description here

以及主线程的堆栈,如果我在引发异常后设置默认的未捕获异常处理程序。

enter image description here


答案 1

您可以先验证 Eclipse 中的此设置是否已启用。

窗口 -> 首选项 -> Java -> 调试 -> 在未捕获的异常时暂停执行

如果启用此设置,则任何未捕获的异常都将在 JVM 引发的位置暂停 JVM,包括使用反射调用的类。这是没有添加任何断点,但前提是它未处理,即您的代码甚至不被来自 try-catch 的外部代码调用。

例如:

int a = 0, b= 0;
System.out.println(a/b); // ArithmeticException

即使此代码是从反射调用的代码中调用的,eclipse 也会在 sysout 挂起,并且堆栈上仍有所有变量可用。

然而,在Android的创业类ZygoteInit中,有这样一行:

    catch (Throwable t) {
                Log.e(TAG, "Error preloading " + line + ".", t);
                if (t instanceof Error) {
                    throw (Error) t;
                }
                if (t instanceof RuntimeException) {
                    throw (RuntimeException) t;
                }
                throw new RuntimeException(t);
            }

这样的代码会破坏Eclipse调试的原因是,现在已经不再无人处理了。您实际上可能正在捕获启动类而不是您的用户代码。这是针对常规日食的。RuntimeExceptionUncaughtExceptionHandler

解决方案 1 :

  1. 转到运行 -> 添加 Java 异常断点 ->Throwable
  2. 在断点视图中单击Throwable
  3. 右键单击 -> 断点属性 ->添加包 -> 确定
  4. 检查此异常的选项子类

enter image description here

注意:这可以勉强抓住一个,但绝对不能抓住一个。java.lang.OutOfMemoryErrorjava.lang.StackOverflowError

解决方案2:仅当捕获的异常过多时,不建议以其他方式使用))

  1. 将源代码复制到新项目说com.android.internal.os.ZygoteInitMyBootstrap
  2. 将块修改为仅捕获catch (Throwable t)Error

        } catch (Error t) {
            Log.e(TAG, "Error preloading " + line + ".", t);
            throw t;
        }
    
  3. 转到调试配置 ->类路径 -> 单击引导程序项 -> 添加项目 -> 。将此项目移到顶部MyBootstrap

enter image description here


答案 2

基本上,如果我正确地理解你,你想要设置一个断点,如果该异常没有/不会随后处理,它将在抛出异常的点触发。

如果这就是你的意思,那么你所要求的基本上是不可能的。

  1. 在引发异常时,调试器无法判断是否要捕获异常。

  2. 在捕获异常的点上,来自投射点的状态(即堆栈帧,变量等)...直到捕捉点...将被丢弃。

  3. Java 调试器 API 不支持调试器可用于此目的的“倒带和重放”机制。


在我看来,你能做的最好的事情是1)确定你怀疑没有被捕获的异常,2)在其构造函数或合适的超类构造函数上设置一个断点,3)找出一些条件来过滤掉不感兴趣的情况,4)逐步执行代码以查看异常是否被捕获。

注意:异常可能会在与实例化位置不同的位置引发或重击,因此异常构造函数断点并不总是有帮助。但它通常会。