2014-12-12 17 views
5

Esiste una parte di codice complessa che esegue molte operazioni matematiche complesse.Incompatibilità tra le versioni java

Quando è stato costruito e testato da maven su jdk 1.7, passa tutti i test. Quando si utilizza jdk 1.8 fallisce.

Cercando di trovare il punto in cui i calcoli vanno male in un debugger sembra quasi senza speranza.

Quali sono le mie opzioni? C'è uno strumento in grado di scansionare le incompatibilità tra jdk 1.7 e 1.8 nel mio codice?

È la mia migliore opzione per eseguire il codice in due debugger separati e vedere dove sarebbe la differenza?

EDIT:

@Philipp Claßen Questa è la causa più probabile finora. Speravo che ci sarebbe stato un modo automatico di controllo per questo.

@dkatzel Il codice non è stato scritto da me, mal commentato e fa calcoli scientifici che sono "woodo" per me.

@ Mike Samuel Non vedo alcun vantaggio di questo approccio sull'esecuzione di due debugger in parallelo.

Grazie a tutti per l'aiuto. Sembra che due debugger siano il modo migliore per andare.

EDIT 2 L'autore del codice originale faceva affidamento sull'ordinamento delle mappe hash. Questo era il problema

+0

Controllare le note di rilascio per gli indizi. Altrimenti, penso che dovrai eseguire due debugger. –

+1

puoi inserire qualche codice? –

+0

Posso garantire che vedere il codice non sarà d'aiuto. A meno che non ti piacerebbe passare attraverso migliaia di righe. – Andrey

risposta

3

Aggiungere istruzioni di registrazione per registrare ogni risultato intermedio. Puoi usare qualcosa come

static void dumpDoubleWithLineNumber(double d) { 
    StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 
    // Thread.getStackTrace() and this method are elements 0 and 1 
    StackTraceElement caller = stack[2]; 
    System.err.println(
     caller.toString() 
     + " : " + d 
     + "/" + Long.toString(Double.toLongBits(d), 16)); 
} 

Quindi eseguirlo una volta in Java 7, una volta in Java 8, e diffare i risultati.

+0

Mi dispiace, ma considerando che ha già casi di test, e il codice è 1000s di righe, non è questo un piccolo approccio di Hello World? Preferirei iniziare con i casi di test e le loro tracce di stack .. – Shaunak

+0

@Shaunak, non so quale sia l'approccio di Hello World, ma le tracce dello stack di test indicano solo dove è stato rilevato l'errore. Una differenza di log da un test fallito ti dirà dove è iniziata la divergenza. 1000 di linee è un programma abbastanza piccolo. Mettere in poche centinaia di dichiarazioni di registro dovrebbe richiedere 20 minuti al massimo. Il tentativo di ragionare all'indietro a causa di un errore di test potrebbe richiedere ore o giorni. –

+0

Esattamente ciò per cui scriviamo i casi di test! e sembra che abbia già una buona serie di casi di test che hanno colto il problema. – Shaunak

3

Sembra che tu abbia una buona serie di test che hanno colto il problema. Forse un buon inizio sarebbe quello di confrontare i test che passano e quelli che falliscono. Che cosa hanno fatto i test che falliscono in modo diverso?

Se i test che falliscono fanno troppo, allora sono necessari più test a grana più fine. I test dovrebbero davvero testare solo una cosa in isolamento. Ciò significa che dovresti avere molti test che testano ciascuna parte del calcolo complesso.

Le nuove versioni di Java in realtà non si sforzano di rompere il vecchio codice di lavoro per cui è improbabile un bug nel JDK ... comunque è possibile ...

+0

Ora questo è un modo migliore per iniziare .. – Shaunak

7

guardare fuori per le fonti di determinismo.

Soprattutto il codice che si basa sull'ordinamento di elementi in raccolte come HashMaps è pericoloso, in quanto l'ordine non è specificato e dipende dalla JVM.

Ho visto in ogni aggiornamento JVM che un tale codice (buggy) ha funzionato per fortuna e si è rotto immediatamente una volta che l'implementazione di JVM è cambiata.

0

Se c'è un oggetto specifico, si desidera monitorare e i punti, dove l'oggetto è cambiato non sono troppi, si potrebbe provare a impostare i breakpoint condizionali , che stamperà le informazioni su System.out invece di sospendendo la discussione. Che funziona bene per Eclipse, può essere anche per altri IDE
Ad esempio, per monitorare il valore d in un punto specifico del codice, si crea un punto di interruzione con la seguente condizione:

System.out.println(Thread.currentThread().getStackTrace()[1] + " value="+d); return false; 

Questa condizione non è mai vero, ma sempre valutati, in modo da esso stampa una cosa del genere:

test.Main.main(Main.java:23) value=1.0 

Se questo funziona nel vostro IDE, è possibile eseguire il programma con Java 7 e Java 8 nell'IDE e confrontando l'uscita. Se è possibile identificare la linea in cui si verificano le differenze, è possibile procedere con il debugging convenzionale.

Puoi trovarne altre qui: http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-manage_conditional_breakpoint.htm