Prima di iniziare, è necessario aver completato l'Esercizio 1.3: Distribuzione dell'analisi.
Probekit può essere utilizzato per risolvere molti problemi di debug e analisi di runtime. Si sono apprese le nozioni base su come scrivere e distribuire le analisi, quindi questa e le prossime lezioni non affronteranno le attività, bensì forniranno suggerimenti per le analisi che si potrebbero scrivere per esaminare l'applicazione in uso.
Presupporre che un metodo in un servlet a volte generi un'eccezione. Il messaggio di log che si ottiene non è di grande aiuto; in quanto non indica chiaramente quale sia il problema. Per avere ulteriori informazioni, è possibile scrivere un'analisi che viene eseguita ogni volta che il metodo genera un'eccezione, e il codice Java nel frammento dell'analisi può registrare il messaggio di eccezione e gli argomenti del metodo. Tale operazione faciliterà la comprensione del perché l'eccezione è stata generata.
Quando si scrive e distribuisce un'analisi, fare attenzione ai seguenti punti:
System.out.println("[Exception probe triggered!]"); for (int i = 0; i < args.length; i++) { System.out.println("Argument " + i + "=" + args[i]); }
Di seguito è riportato un esempio di analisi abbastanza complicato. Presupponiamo che vi sia un metodo nel programma in uso che solitamente viene eseguito rapidamente ma a volte necessita molto tempo per la propria esecuzione (ad esempio più di 100 ms).
È possibile scrivere un'analisi che prenda nota dell'ora di inizio e di fine di esecuzione del metodo. Quando il tempo di esecuzione è breve, l'analisi non esegue nulla. Quando il tempo di esecuzione è lungo, l'analisi riporta gli argomenti al metodo e altre importanti informazioni riguardo allo stato e ai tempi del programma. Ciò consente di determinare le circostanze che portano a tempi di esecuzione più lunghi.
Quando si scrive un'analisi, fare attenzione ai seguenti punti:
È possibile utilizzare la funzione "frammento a livello di classe" di Probekit per scrivere un frammento di codice Java che verrà compilato nella classe generata al di fuori di qualsiasi metodo. In tal caso il frammento è utilizzato per definire un campo statico chiamato entryTime che verrà utilizzato sia dai frammenti in entrata che quelli in uscita.
Per aggiungere tale elemento ad un'analisi, fare clic sull'elemento Analisi nell'editor di analisi. L'editor visualizza un campo dove inserire il codice Java per il frammento a livello di classe:
static long entryTime; static final long thresholdDuration = 100;
entryTime = System.currentTimeMillis();
long now = System.currentTimeMillis(); if ((now - entryTime) > thresholdDuration) { System.out.println( "[Spent a long time in " + className + "." + methodName + ": this=" + thisObject + "]"); }
All'entrata di un metodo tale analisi registra l'ora corrente. All'uscita del metodo, l'analisi confronta l'ora attuale con quella di entrata, e se è trascorso più di un certo lasso di tempo (il tempo che è stato specificato in "thresholdDuration"), stampa un rapporto utilizzando System.out.
L'analisi appena esaminata non può essere utilizzata per i metodi che sono ricorsivi (direttamente o indirettamente) e nemmeno per quei metodi che potrebbero essere eseguiti su più thread contemporaneamente. Per risolvere il problema della ricorsività, è possibile registrare gli orari di entrata su di uno stack; per risolvere il problema su più thread, è possibile memorizzare lo stack in una variabile ThreadLocal.
Di seguito è riportato ciò di cui si necessità per una versione di analisi protetta ricorsiva e thread:
static ThreadLocal tl = new ThreadLocal() { public Object initialValue() { return new Stack(); } }; static long thresholdDuration = 100; // Report if time is over 100ms
long now = System.currentTimeMillis(); Stack stk = (Stack)tl.get(); stk.push(new Long(now));
long now = System.currentTimeMillis(); Stack stk = (Stack)tl.get(); long entryTime = ((Long)stk.pop()).longValue(); if (now - entryTime > thresholdDuration) { System.out.println( "[Spent a long time in " + cName + "." + mName + ": this=" + thisObj + "]"); }
Continuare l'esercitazione con l'Esercizio 1.5: Uso di una libreria di runtime per una logica di analisi più complessa.