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:
- le variabili locali non sono mai coerente poiché il campo si può accedere da diversi metodi,
- le variabili membro della classe da cui accesso è invocato non sono mai coerente poiché il campo si può accedere da più classi,
- le classi importate disponibili nel contesto di esecuzione non sono mai coerenti per lo stesso motivo di (2) e
- 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.
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