Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eclipse - break on user code when unhandled exception is raised on Android App

My problem is simple :

  • I use Ecplise (Luna or Neon) to develop on Android and I don't want to use Android Studio

  • I wish to debug breaks on ALL unhandled exceptions only on the last user code call of the stack that cause the exception (So, for example, I don't want to break in an unuseful ZygonteInit&MethodAndArgsCaller.run() when an exception in caused by passing a null reference to a native Android SDK method).

I know that I can set a break point for a particular exception in the breakpoint view (NullPointerException..Throwable...) but I want to break on ALL unhandled. I know that I can filter debug by setting "step filters" in Java debug option, but in my case this doesn't work for all exception.

EDIT

In the image below my stack in debug View when an exception is raised (a division by zero in my code)

enter image description here

And the stack of the main thread if I set a default Uncaught Exception Handler after exception is raised.

enter image description here

like image 774
christian mini Avatar asked Jun 17 '16 21:06

christian mini


People also ask

What is the exception in Android?

An exception thrown when an error occurs during parsing. The object you are calling has died, because its hosting process no longer exists. The core Android system has died and is going through a runtime restart. Exception thrown when the provisioning server or key server denies a certficate or license for a device.

How do I get exceptions in Eclipse?

If an error occurs, Java goes to the catch block and runs that. In Eclipse, just surround the code you want to enclose with the try-catch block and right-click, then select **Surround with > Try Catch **block. Although you can only have one try statement per try-catch block, you can have multiple catch blocks.

What is Eclipse exception?

Exceptions are special types defined by the exception keyword: exception FooException; Exceptions can be thrown, which returns control flow to the caller. If the exception is not caught by the caller it propagates further. If the exception is never caught it causes a system reset.


1 Answers

You can first verify if this setting in Eclipse is enabled.

Window -> Preferences -> Java -> Debug -> Suspend execution on uncaught exceptions

If this setting is enabled, any uncaught exception will suspend the JVM exactly at the point its thrown, including classes invoked using reflection. This is without adding any breakpoint, but provided its unhandled, i.e. your code is not even invoked by an external code from a try-catch.

For e.g.

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

Even if this code is called from a reflection invoked code, eclipse will suspend at sysout with all variables still available on the stack.

However in Android's startup class ZygoteInit there is this line :

    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);
            }

The reason why such code would break Eclipse debugging is, the RuntimeException is now no more unhandled. Your UncaughtExceptionHandler may actually be catching the startup class instead of your user code. This is for regular Eclipse.

Solution 1 :

  1. Goto Run -> Add Java Exception Breakpoint -> Throwable
  2. Click on Throwable in the Breakpoint view
  3. Right click -> Breakpoint properties -> Add package -> OK
  4. Check on the option Subclasses of this exception

enter image description here

Note : This can marginally catch a java.lang.OutOfMemoryError but definitely cannot catch a java.lang.StackOverflowError.

Solution 2 : (Only if too many caught exceptions, NOT recommended otherwise)

  1. Copy the source code of com.android.internal.os.ZygoteInit to a new project say MyBootstrap
  2. Modify the catch (Throwable t) block to catch only Error

        } catch (Error t) {
            Log.e(TAG, "Error preloading " + line + ".", t);
            throw t;
        }
    
  3. Go-to debug configurations -> Classpath -> Click Bootstrap Entries -> Add projects -> MyBootstrap. Move this project to the top

enter image description here

like image 100
Rajeev Sreedharan Avatar answered Sep 25 '22 06:09

Rajeev Sreedharan