2010-02-17 30 views
34

Desidero jdb (che sto utilizzando tramite il debugger Eclipse) per interrompere quando a una variabile viene assegnato un valore. Non mi interessa impostare un breakpoint su una linea specifica ma piuttosto in generale.Interruzione quando a una variabile viene assegnato un valore

Ad esempio, interrompere ogni volta x == null.

È una cosa possibile?

+0

Quello che stai cercando è qualcosa come un [listener di modifica proprietà] (http://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html) che ti consente di rilevare una modifica specifica e cattura la traccia dello stack. Non credo che questo sia ancora disponibile in qualsiasi debugger e sarà difficile da implementare se gli sviluppatori della libreria originale non lo hanno trasformato in una proprietà. – Cebence

risposta

5

Sì, quelli sono chiamati watchpoints, e watchpoints può avere orologi espressioni.

A seconda delle versioni e così via, è possibile farlo selezionando una variabile nella vista Struttura e facendo clic con il pulsante destro del mouse su di essa o nella vista Variabili, facendo clic su di esso.

un menu contestuale avrà alberghi per Aggiungi controllo Espressione e Modifica faccia espressione.

+0

Ho giocato con i watchpoint ma non sembrano essere colpiti a meno che non definisco il punto di controllo quando la variabile è in ambito. Posso definire un punto di controllo e farlo abilitare quando la variabile controllata entra in campo? C'è un modo per qualificare i nomi delle variabili controllate? – Daniel

+0

Questo non sembra consentire solo l'interruzione quando viene trovato un valore specifico. – mjaggard

31

Sì - Quello che è necessario impostare è un "Conditional Breakpoint" - questo consente di interrompere l'esecuzione del programma e di eseguire il debugger quando viene raggiunto un determinato stato dell'applicazione.

Quindi, diciamo che si vuole saltare in un punto particolare nell'esecuzione quando una determinata condizione è soddisfatta (come da immagine allegata), si può fare questo come segue:

  1. Aprire il debugger prospettiva e selezionare i punti di interruzione '' scheda

  2. Aggiungi un nuovo punto di interruzione nel file di codice - in un punto specifico in cui si desidera osservare l'esecuzione del programma

  3. Poi tornare alla scheda 'Punti di interruzione', tasto destro del mouse sulla voce appena aggiunta e selezionare 'Breakpoint Properties'

  4. Impostare la condizione su cui deve essere attivata

alt text

+5

Ciao Diunk, Il tuo suggerimento non dipende dal fatto che la condizione sia soddisfatta a un particolare numero di linea? Vorrei una soluzione più generale che ovvi alla necessità di identificare i numeri di riga. Voglio solo sapere quando "x" è assegnato a qualcosa, indipendentemente dal metodo in cui avviene l'assegnazione. – Daniel

+0

Ciao Daniel, Le tue domande dichiarano ogni volta che "x" (una variabile) viene impostata su un determinato valore per il quale si desidera interrompere il flusso di controllo. Le domande sono, dove? Bene, se ci pensate, "x" deve essere un'istanza o una variabile locale. In entrambi i contesti sapresti esattamente quale riga della tua fonte vorresti osservare, non è vero? (il setter o l'ambito del blocco locale). Da quel punto, chiami lo stack delle chiamate e il backtrack. – Dinuk

+3

Hi Diunk, In realtà stavo cercando di eseguire il debug di un problema in una libreria che non è mia. La variabile è protetta e esiste una gerarchia di tipi ragionevolmente ampia che estende la classe base in cui è definita. L'accesso potrebbe essere in molti luoghi ed è per questo che volevo un breakpoint senza contesto. Sembra che thSoft e DigitalRoss siano corretti nel loro suggerimento. – Daniel

0

Ci dispiace, ma non c'è modo di fare ciò che vuoi in Eclipse. Quello di cui hai bisogno è un punto di osservazione con l'espressione condizionale di un punto di interruzione. Non esiste in Eclipse.

Il tuo problema è anche il debug specifico di una libreria. Ci sono probabilmente altri modi per ottenere ciò di cui hai bisogno. Cerca nel forum per vedere come lo fanno gli sviluppatori.

8

È possibile avvicinarsi allo. Sono limitati a essere posizionati su campi di oggetti (non variabili locali, parametri o espressioni) e vengono attivati ​​ogni volta che il campo viene scritto, ma è il più vicino che Eclipse ha a disposizione.

+0

+1 Ma notate: oltre ad essere limitato a campi (che sembra essere ok con il requisito dell'OP), si innescherà non esattamente quando cambia, ma quando è _critto_ (anche quando è scritto con lo stesso valore precedente). – leonbloy

9

Modifica: The ticket I've linked in this answer è stato contrassegnato come verificato/corretto. È stato integrato nell'ultima versione di Oxygen, as detailed in the release notes.Lascerò qui sotto la mia risposta originale poiché contiene molte informazioni utili su come JDI e JDT lavorano insieme in Eclipse.


ho intenzione di iniziare con la risposta finale alla tua domanda in modo da non dover leggere i dettagli se non si vuole. Fondamentalmente, questo è un po 'possibile ma con un sacco di domande che devono essere risolte prima. Se vuoi saltarlo e andare direttamente al biglietto, here you go, ma ti consiglio di continuare a leggere.

Eclipse utilizza JDI (molto in fondo a tale pagina) per registrare i watchpoint con JVM. Questo viene fatto attraverso i metodi EventRequestManager (l'implementazione è fornita dalla stessa JVM, non da Eclipse) che creano watchpoint, ovvero EventRequstManager.createModificationWatchpointRequest. L'unica cosa accettata da questi metodi è un Field (nota che questa non è la classe riflettente Field). Quindi, in breve, Eclipse non può farlo direttamente tramite Java. Non temere mai, Java non gestisce neanche i break condizionali. Anche questi vengono implementati direttamente tramite Eclipse anziché fare affidamento su Java. Ci sono, tuttavia, alcuni avvertimenti che rendono i watchpoint condizionali molto più difficili da implementare rispetto ai breakpoint condizionali.

Consideriamo chiari punti di interruzione condizionali. Affinché funzionino, è necessario un contesto in cui è possibile eseguire lo snippet di codice. Senza un contesto di esecuzione per il codice, non possiamo valutare le espressioni/istruzioni nello snippet poiché non abbiamo modo di risolvere variabili, valori, tipi, ecc. Questo viene fatto usando un parser AST che elabora il codice Java in istruzioni reali . Ricorda che puoi digitare un numero di istruzioni in una condizione, non solo una singola espressione. Il valutatore utilizza quindi un contesto (in particolare, uno IJavaStackFrame) per valutare l'espressione stessa dopo averlo analizzato.

Ora pensa a un punto di controllo condizionale, perché quest'ultimo punto è molto importante. Qual è il contesto di esecuzione di un watchpoint? L'accesso alle variabili può avvenire non solo all'interno della stessa classe, ma anche in altre classi (si pensi allo protected e ai membri del pacchetto), e anche nelle classi interne (tramite MyClass.this.myField). Ciò significa che:

  1. le variabili locali non sono mai coerente poiché il campo si può accedere da diversi metodi,
  2. le variabili membro della classe da cui accesso è invocato non sono mai coerente poiché il campo si può accedere da più classi,
  3. le classi importate disponibili nel contesto di esecuzione non sono mai coerenti per lo stesso motivo di (2) e
  4. l'accesso del campo stesso non è mai consistente poiché potrebbe richiedere la qualifica con un'istanza, nome classe, super o con qualcosa come MyClass.this.myField (per l'accesso alla classe interna).

La fattibilità di tale funzione è di tipo limitato. Sareste costretti a valutare effettivamente una dichiarazione condizionale non mutevole per un punto di controllo poiché assolutamente nulla nel contesto dell'esecuzione sarà coerente. Ciò significa che il codice non può essere facilmente analizzato e interpretato senza significato speciale applicato alle parti del codice, come:

myField è sempre uguale this.myField o super.myField o MyClass.myField o MyClass.this.myField, a seconda di dove il campo è accesso.

questo complica le cose un po ', soprattutto in un sistema che è già relativamente complessa. È possibile trovare un esempio del codice del punto di interruzione condizionale here (cercare getEvaluationEngine utilizzando Ctrl + F). Ora prendi questo e aggiungi la pre-elaborazione all'espressione sulla base di un insieme di regole su dove siamo e dove si trova il campo, e fare le cose può diventare complicato.

AFAIK, non si può fare qualcosa del tipo, "se il valore vecchio/nuovo è questo, sospendi", perché tali informazioni semplicemente non sono disponibili dalle informazioni che si possono ottenere nello stack frame (e quindi dal debugger). L'espressione assegnata al valore è stata valutata dal momento in cui il watchpoint viene colpito, ma il risultato non è disponibile per il debugger, pertanto non è disponibile per un valutatore sul watchpoint stesso. Un passaggio dovrebbe essere eseguito prima per eseguire l'assegnazione, quindi l'espressione dovrebbe essere valutata dopo il passo. Sarebbe terribilmente disordinato, e onestamente, piuttosto hacky in questo.

In ogni caso, se si desidera fornire assistenza per questa funzione, è possibile utilizzare this Eclipse ticket. Tuttavia, è in circolazione dal 2005 (8 anni fa) e ha un supporto limitato da parte della comunità. TBH, non vedo che vada molto lontano, soprattutto senza ulteriori chiarimenti sulle aspettative dietro questo tipo di richiesta di funzionalità e senza alcune considerazioni importanti sul design che sono state messe in primo piano.

+0

penso che sarebbe una buona funzionalità. votato per questo – tgkprog

+0

Esattamente il tipo di risposta che speravo. Grazie.Non sono sicuro che voterò a favore o no, sono d'accordo che suona molto complesso ma non dovrebbe essere complesso quindi suppongo che la prossima domanda sia dove si trova il bug report Java. (Ma questa è una domanda completamente e assolutamente inutile, a meno che non lavori per Oracle perché i voti della community valgono meno dello zero per gli attuali manutentori Java) – mjaggard

+0

@mjaggard Ancora peggio è l'attuale bug del database Oracle privato e puoi accedervi solo se pagare per un contratto di supporto Oracle. Il database dei bug di OpenJDK è aperto però. – Brian

Problemi correlati