2015-02-15 16 views
5

Więc ja rozpoczynam program Java, jak poniżejAttach JDB na nieprzechwyconego wyjątkiem

java -agentlib:jdwp=transport=dt_socket,address=8000, server=y,suspend=n MyClass 

Następnie ręcznie dołączyć debugger jak poniżej

jdb -attach 8000 

chciałbym wiedzieć, czy istnieje w każdym razie dla mnie skonfigurować jdb tak, aby automatycznie przyłączał się do działającego procesu (tylko) w przypadku nieprzechwyconego wyjątku?

Powodem jest to, że chciałbym uniknąć obciążenia debuggera, aż pojawi się nieprzechwycony wyjątek. Problemem, z którym teraz borykam się, jest to, że jeśli debugger nie jest podłączony, wówczas JVM przerwie się, gdy pojawi się nieprzechwycony wyjątek.

EDIT:

Od Wyroczni docs wydaje polecenie poniżej robi to, co muszę, ale dla komputerów z Windows.

java -agentlib:jdwp=transport=dt_shmem,server=y,onuncaught=y,launch=d:\bin\debugstub.exe MyClass 

Ktoś zna odpowiednik linuksa? Próbowałem polecenia poniżej.

java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,onuncaught=y,suspend=n,launch=jdb MyClass 

Debugger wygląda na to, że łączy się, ale natychmiast rzuca IOError.

Initializing jdb ... 

java.io.IOException: Input/output error 
at java.io.FileInputStream.readBytes(Native Method) 
at java.io.FileInputStream.read(FileInputStream.java:272) 
at java.io.BufferedInputStream.read1(BufferedInputStream.java:273) 
at java.io.BufferedInputStream.read(BufferedInputStream.java:334) 
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283) 
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325) 
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177) 
at java.io.InputStreamReader.read(InputStreamReader.java:184) 
at java.io.BufferedReader.fill(BufferedReader.java:154) 
at java.io.BufferedReader.readLine(BufferedReader.java:317) 
at java.io.BufferedReader.readLine(BufferedReader.java:382) 
at com.sun.tools.example.debug.tty.TTY.<init>(TTY.java:751) 
at com.sun.tools.example.debug.tty.TTY.main(TTY.java:1067) 

Odpowiedz

0

Zamiast używać debuggera i dołączenie jednego zdalnie, dlaczego nie można utworzyć uncaught exception handler użyciu Thread.UncaughtExceptionHandler?

public class ThreadCatch 
{ 
    public static void main(String... args) 
    { 
     new ThreadCatch().go(); 
    } 

    public void go() 
    { 
     try { 
      Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
       @Override 
       public void uncaughtException(Thread t, Throwable e) { 
        System.out.println("Uncaught exception"); 
        e.printStackTrace(); 
       } 
      }); 

      final Thread thread = new Thread(new A()); 
      thread.start(); 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    class A implements Runnable 
    { 
     int x = 10; 

     @Override 
     public void run() 
     { 
      x++; 
      ObjectTrackingException obj = new ObjectTrackingException(); 
      obj.setThrownFrom(this); 
      throw obj; 
     } 
    } 
} 


class ObjectTrackingException extends RuntimeException 
{ 
    private Object thrownFrom; 

    public Object getThrownFrom() { 
     return thrownFrom; 
    } 

    public void setThrownFrom(Object thrownFrom) { 
     this.thrownFrom = thrownFrom; 
    } 
} 

enter image description here

+0

Cóż, chcę analizować wartości zmiennych na stosie w momencie awarii programu. Nie sądzę, że mogę to zrobić z UncaughtExceptionHandler, ponieważ stos rozwinie się, gdy wyjątek przejdzie w górę? – nave

+0

Dlaczego nie ustawić warunkowego punktu przerwania na module obsługi wyjątku? W ten sposób uzyskasz wyjątek, a punkt przerwania pozwoli ci przejrzeć stos wywołań. –

+0

Tak więc, jak rozumiem, kiedy wyjątek jest rzucany od, powiedzmy, metodę B, stos wywołań dla metody jest niszczony, a wyjątek jest rzucany w górę. To się toczy, aż w końcu wyjątek dotrze do UncaughtExceptionHandler. Ale do tego czasu stos wywołań metody, w której wystąpił wyjątek (i którego zmienne lokalne chcę wyświetlić) już nie istnieje. Czy warunkowy punkt przerwania nie pomoże? Daj mi znać, jeśli coś jest nie w porządku z moim zrozumieniem ... – nave

3

Aby dołączyć debugera w sam raz rzeczywiście użyć opcji proponujesz (launch i onuncaught). Ale opcja launch potrzebuje więcej na Linuksie:

Należy zauważyć, że rozpoczęty proces nie rozpoczął się we własnym oknie. W większości przypadków uruchomiony proces powinien być małą aplikacją, która z kolei uruchamia aplikację debuggera we własnym oknie.

W twoim przypadku, JDB nie udaje się otworzyć zacisk TTY potrzebuje ze względu na kontekst jest on uruchomiony. W zależności od środowiska, w którym to działa, trzeba będzie zbudować skrypt, który uruchamia JDB w nowe okno lub dołącza je do pseduo-tty, aby działał poprawnie.

testowałem to poprzez stworzenie skryptu, który używa screen aby uruchomić terminal

#!/bin/bash 
# according to launch option doc, the first argument is the transport and 
# the second argument will be the address 
# 
screen -dm -L -S autojdb jdb -attach $2 

Ten skrypt rozpocznie jdb w jednorodzinnym ekranie, a nazwa sesji dla ekranu autojdb. Listę ekranów możesz zobaczyć, używając screen -ls. Jeśli chcesz uzyskać dostęp do debuggera, który został uruchomiony, użyj screen -r autojdb.Upewnij się, aby umieścić skrypt na swojej drodze lub podać pełną ścieżkę (/home/me/screenjdb poniżej) w opcji wprowadzenia:

java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,onuncaught=y,suspend=n,launch=/home/me/screenjdb MyClass 

W moim skryptu I również przeszedł -L do ekranu, który rejestruje sesję. Spowoduje to rejestrację sesji, ale także pozwoli zobaczyć wszelkie błędy, które wystąpiły, jeśli dołączenie nie powiedzie się z jakiegoś powodu.

Powiązane problemy