Eclipse - 在Android App上引发未处理的异常时中断用户代码

时间:2016-06-17 21:00:50

标签: java android eclipse debugging

我的问题很简单:

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

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

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

修改

在调试视图下面的图像中,当引发异常时(我的代码中除以零)

enter image description here

如果我在引发异常后设置了默认的Uncaught Exception Handler,则主线程的堆栈。

enter image description here

2 个答案:

答案 0 :(得分:1)

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

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

  1. 在抛出异常时,调试器无法判断是否会捕获异常。

  2. 在捕获到异常的位置,从抛出点到捕获点的状态(即堆栈帧,变量等)将被丢弃。

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

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

    注意:异常可能会被抛出或重新抛出到实例化它的不同位置,因此异常构造函数断点并不总是有用。但它通常会。

答案 1 :(得分:1)

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

窗口 - >偏好 - > Java - >调试 - >暂停执行未捕获的异常

如果启用此设置,则任何未捕获的异常都会将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调试的原因是,RuntimeException 现在不再是未处理的。您的UncaughtExceptionHandler实际上可能正在捕获启动类而不是您的用户代码。这适用于常规Eclipse。

解决方案1:

  1. Goto Run - >添加Java异常断点 - > Throwable
  2. 点击断点视图中的Throwable
  3. 右键单击 - >断点属性 - > 添加包 - >行
  4. 选中此例外的子类
  5. 选项

    enter image description here

    注意:这可以轻微捕获java.lang.OutOfMemoryError,但肯定无法捕获java.lang.StackOverflowError

    解决方案2:仅当捕获的异常太多时,否则不推荐

    1. com.android.internal.os.ZygoteInit的源代码复制到新项目MyBootstrap
    2. 修改catch (Throwable t)块以仅捕获Error

          } catch (Error t) {
              Log.e(TAG, "Error preloading " + line + ".", t);
              throw t;
          }
      
    3. 转到调试配置 - > Classpath - >单击Bootstrap条目 - >添加项目 - > MyBootstrap。将此项目移至顶部

    4. enter image description here

相关问题