2016-06-17 20 views
17

Mój problem jest prosty:Eclipse - przerwa na kod użytkownika podczas nieobsługiwany wyjątek jest podniesione w Android App

  • używam Ecplise (Luna neonowych), aby rozwijać na Androida i nie chcę używać Androida Studio

  • pragnę przerw debugowania na WSZYSTKICH nieobsłużonych wyjątków jedynie w ostatnim użytkownika wywołania kodu stosu, które powodują wyjątek (Tak więc, na przykład, nie chcę złamać w unuseful ZygonteInit & MethodAndArgsCaller .run(), gdy wyjątek spowodowany jest przez przekazanie pustego odwołania do a natywna metoda Android SDK).

wiem, że mogę ustawić punkt przerwania dla danego wyjątkiem punktu przerwania w widoku (NullPointerException..Throwable ...) ale chcę złamać na ALL nieobsługiwany. Wiem, że mogę filtrować debugowanie, ustawiając "filtry kroków" w opcji debugowania Java, ale w moim przypadku to nie działa dla wszystkich wyjątków.

EDIT

Na obrazku poniżej mojego stosu w debugowania View gdy jest wyjątek (dzielenie przez zero w moim kodu)

enter image description here

A stos głównym wątku jeśli ustawię domyślny Uncaught Exception Handler po podniesieniu wyjątku.

enter image description here

+1

chciałbym spróbować wykonać następujące czynności: 1. Wdrożenie własny zwyczaj UncoughtExceptionHandler (patrz [Using Globalny Exception Handling na Android] (http://stackoverflow.com/questions/4427515/using-global-exception-handling-on-android)) i 2. Użyj warunkowego punktu przerwania na tym module obsługi - dla warunku sprawdź śledzenie stosu, jeśli zawiera on jedną z twoich klas. – Robert

+0

@Robert Dziękujemy za sugerowane rozwiązanie. Próbowałem tego rozwiązania, ale problem polega na tym, że UncoughtExceptionHandler jest obsługiwany przez inny wątek, podczas gdy wątek powodujący wyjątek właśnie się zakończył i nie jest dostępny na stosie. –

+0

@christianmini: Wątek jest dostępny na stosie? W tym zdaniu jest coś nie tak –

Odpowiedz

1

Najpierw sprawdź, czy to ustawienie w Eclipse jest włączone.

Window -> Preferences -> Java -> Debug -> zawiesić wykonywanie na Uncaught wyjątkami

Jeśli ta opcja jest włączona, każde przechwycony wyjątek zawiesza JVM dokładnie w miejscu jego rzucony, w tym klas przywoływanych za pomocą refleksji. Jest to bez dodawania żadnego punktu przerwania, ale pod warunkiem, że jego nieobsługiwany, tj. Twój kod nie jest nawet wywoływany przez zewnętrzny kod z try-catch.

Dla np.

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

Nawet jeśli ten kod jest wywoływana z refleksji wywołany kod, zaćmienie będzie zawiesić na sysout ze wszystkich zmiennych wciąż dostępnych na stosie.

Jednak w Android klasie startowejZygoteInit jest ta linia:

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

Powodem takiego kodu złamie Eclipse debugowanie to, że RuntimeException jest teraz nie więcej nieobsługiwany. Twój UncaughtExceptionHandler może faktycznie przechwytywać klasę uruchamiania zamiast kodu użytkownika. To jest dla zwykłego Eclipse.

Rozwiązanie 1:

  1. Goto Uruchom -> Dodaj Java Wyjątek Breakpoint ->Throwable
  2. Click on Throwable w Breakpoint widzenia
  3. Prawy przycisk myszy -> Właściwości Breakpoint ->dodawania pakietu -> OK
  4. Sprawdź opcję Podklasy tego wyjątku

enter image description here

Uwaga: To może nieznacznie złapać java.lang.OutOfMemoryError ale zdecydowanie nie może złapać java.lang.StackOverflowError.

Rozwiązanie 2: (Tylko jeśli zbyt wiele złowione wyjątki, a nie zaleca inaczej)

  1. skopiować kod źródłowy com.android.internal.os.ZygoteInit do nowego projektu mówią MyBootstrap
  2. Modyfikacja bloku catch (Throwable t) do złap tylko Error

    } catch (Error t) { 
         Log.e(TAG, "Error preloading " + line + ".", t); 
         throw t; 
        } 
    
  3. Go-to konfiguracje debugowania -> Classpath -> Kliknij pozycje Bootstrap -> Dodaj projekty ->MyBootstrap.Przenieść ten projekt na górę

enter image description here

+0

Myślę, że rozumiesz problem: "Wyjątek RuntimeException nie jest już nieobsługiwany", więc muszę wybrać obiekt nadrzędny poza wszystkimi wyjątkami Java Runtime, "Throwable", i I Aby wybrać "Caught Location" e "Podklasa tego wyjątku". Ok, jedynym problemem jest to, że podczas cyklu aplikacji na Androida jest setka Caught Exception w kodzie użytkownika lub SDK, czy istnieje sposób na filtrowanie? –

+0

@christianmini Cóż, w takim przypadku 'catch' nie może być deterministyczny. Co powiesz na bootstraping 'ZygoteInit' z' catch (Throwable t) 'usuniętym do debugowania? Ponieważ ta klasa jest przeznaczona do uruchamiania i nie wykonuje połączeń natywnych, powinna wystarczyć do debugowania. W ten sposób nieobsługiwany wyjątek pozostaje nieobsługiwany. –

+0

Myślę, że to może działać. Akceptuję twoją odpowiedź –

1

Zasadniczo, jeśli rozumiem zostanie poprawnie, chcesz ustawić punkt przerwania, które wyzwoli w miejscu, gdzie jest wyjątek jeśli ten wyjątek nie jest/nie będzie odbywać się w terminie późniejszym.

Jeśli o to ci chodzi, to to, o co prosisz, jest w zasadzie niemożliwe.

  1. W momencie, gdy wyjątek zostanie zgłoszony, debugger nie może stwierdzić, czy wyjątek zostanie przechwycony.

  2. W punkcie, w którym przechwycono wyjątek, stan (tj. Ramki stosów, zmienne itp.) Od punktu rzutu ... aż do punktu catch ... zostanie odrzucony.

  3. Interfejsy API debuggera Java nie obsługują mechanizmu "przewiń i odtwórz", który może zostać użyty do debuggera.


Moim zdaniem to najlepsze co możesz zrobić, to: 1) zidentyfikować wyjątek, że podejrzany nie jest złapany, 2) ustawić punkt przerwania na jej konstruktora lub na odpowiednim konstruktor nadklasy, 3) wymyśl pewne warunki, aby odfiltrować przypadki, które nie są interesujące, i 4) przejdź przez ten kod, aby zobaczyć, czy wyjątek został złapany, czy nie.

Uwaga: wyjątek może być zgłoszony lub zgłoszony ponownie w innym miejscu, w którym został utworzony, więc wyjątek konstruktora przerwania nie zawsze pomoże. Ale zwykle tak będzie.

+0

Sądzę, że istnieje kilka bibliotek, które mają "złapać Throwable" z prawdziwych powodów, ale ukryte głęboko w sobie, powodując taką niejednoznaczność podczas debugowania. Może być podobny ogólny przypadek powinien iść do dokumentacji SO dla Java/Exception. –

+0

Moja odpowiedź nie mówi o wychwytywaniu wyjątków. I nie mogę wymyślić uzasadnionego powodu, aby stworzyć przykład "Throwable". –

+0

Co do sugestii Dokumentacji SO ... nie mamy jeszcze nic ważnego w technikach debugowania Javy. (Oprócz jednego przykładu, jak odczytać stos stosu.) –