2015-02-15 2 views
5

Quindi, sto iniziando un programma Java, come di seguitoFissare jdb su eccezioni non rilevate

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

ho quindi collegare manualmente un debugger, come di seguito

jdb -attach 8000 

Vorrei sapere se v'è comunque per io per configurare jdb in modo che si attacchi automaticamente al processo in esecuzione (solo) nel caso di un'eccezione non rilevata?

Il motivo è che vorrei evitare il sovraccarico del debugger fino a quando non si presenta un'eccezione non rilevata. Ma il problema che devo affrontare ora è che se il debugger non è collegato, la JVM si interrompe una volta che si verifica un'eccezione non rilevata.

EDIT:

Dal Oracle docs, sembra il seguente comando fa quello che mi serve, ma per le macchine Windows.

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

Qualcuno conosce l'equivalente di Linux? Ho provato il comando qui sotto.

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

Il debugger sembra si connette ma lancia immediatamente un 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) 

risposta

0

Invece di utilizzare un debugger e allegando una distanza, perché non si crea un uncaught exception handler utilizzando 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

Bene, voglio analizzare i valori delle variabili nello stack al punto di arresto anomalo del programma. Non penso di poterlo fare con UncaughtExceptionHandler dato che lo stack si srotolerà mentre l'eccezione passa al rialzo? – nave

+0

Perché non impostare un breakpoint condizionale sul gestore delle eccezioni, quindi? In questo modo ottieni l'eccezione e il punto di interruzione ti consente di sfogliare lo stack delle chiamate. –

+0

Quindi, a quanto ho capito, quando viene lanciata un'eccezione, diciamo un metodo B, lo stack di chiamate per il metodo viene distrutto e l'eccezione viene sollevata verso l'alto. Questo procede, finché l'eccezione raggiungerà l'UncaughtExceptionHandler. Ma a questo punto, lo stack di chiamate del metodo in cui inizialmente si è verificata l'eccezione (e le cui variabili locali desidero visualizzare) non è più presente. Quindi una rottura condizionale non aiuterà? Per favore fatemi sapere se c'è qualcosa di sbagliato nella mia comprensione ... – nave

3

Per collegare un debugger just in time non effettivamente utilizzare le opzioni che suggeriscono (launch e onuncaught). Ma l'opzione launch ha bisogno di più su linux:

Si noti che il processo avviato non viene avviato nella propria finestra. Nella maggior parte dei casi il processo avviato dovrebbe essere una piccola applicazione che a sua volta avvia l'applicazione debugger nella propria finestra.

Nel tuo caso, JDB non riesce a aprire il terminale TTY di cui ha bisogno a causa del contesto esso viene avviato in. A seconda dell'ambiente in cui questo è in esecuzione, è necessario costruire uno script che lancia jdb in una nuova finestra o la allega ad un pseduo-tty in modo che possa funzionare correttamente.

Ho provato questo con la creazione di uno script che utilizza screen per avviare il terminale

#!/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 

Questo script inizierà jdb in uno schermo indipendente e denominare la sessione per lo schermo autojdb. Puoi vedere l'elenco dei tuoi schermi usando screen -ls. Quando si desidera accedere al debugger che è stato avviato, utilizzare screen -r autojdb.Assicurati di inserire lo script nel vostro percorso o dare il percorso completo (/home/me/screenjdb sotto) nella vostra opzione di avvio:

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

Nel mio script che ho anche passato -L per schermo che registra la sessione. Questo registrerà la sessione ma ti permetterà anche di vedere eventuali errori che si sono verificati se il collegamento non riesce per qualche motivo.