Bevor Sie mit dieser Übung beginnen, sollten Sie Übung 1.3: Sonde implementieren ausgeführt haben.
Mit dem Probekit können Sie viele reale Probleme beim Debug und bei der Laufzeitanalyse lösen. Sie verfügen jetzt über die Basiskenntnisse für das Schreiben und das Deployment von Sonden. In dieser und der folgenden Lektion werden Sie sich mit Vorschlägen für Sonden beschäftigen, die Sie zur Untersuchung Ihrer eigenen Anwendung schreiben könnten.
Nehmen wir an, eine Methode in einem Servlet löst sporadisch eine Ausnahme aus. Die Protokollnachricht, die daraufhin angezeigt wird, ist nicht sehr hilfreich, da sie das Problem nicht klar bezeichnet. Wenn Sie weitere Informationen benötigen, können Sie eine Sonde schreiben, die immer dann ausgeführt wird, wenn die Methode eine Ausnahme auslöst. Die Ausnahmenachricht und die Argumente für die Methode können vom Java-Code im Sondenfragment protokolliert werden. Auf diese Weise können Sie sehen, warum die Ausnahme ausgelöst wird.
Beachten Sie beim Schreiben und beim Deployment dieser Sonde die folgenden Punkte:
System.out.println("[Ausnahmesonde ausgelöst!]"); for (int i = 0; i < args.length; i++) { System.out.println("Argument " + i + "=" + args[i]); }
Hier folgt ein recht kompliziertes Beispiel für eine Sonde. Nehmen wir an, Ihr Programm enthält eine Methode, die in der Regel schnell ausgeführt wird, gelegentlich jedoch lange Zeit benötigt (z. B. länger als 100 ms).
Sie können eine Sonde schreiben, die die Zeit des Eintritts in die Methode und des Austritts aus der Methode registriert, sobald die Methode ausgeführt wird. Wenn die Ausführungszeit kurz ist, unternimmt die Sonde nichts. Bei langer Ausführungszeit meldet die Sonde die Argumente für die Methode sowie andere wichtige Informationen zum Programmstatus und zur Zeit. Auf diese Weise können Sie bestimmen, unter welchen Umständen es zu längeren Ausführungszeiten kommt.
Beachten Sie beim Schreiben der Sonde die folgenden Punkte:
Mit dem Probekit-Feature FragmentAtClassScope können Sie ein Java-Codefragment schreiben, das außerhalb aller Methoden in die generierte Klasse kompiliert wird. In diesem Fall wird mit dem Fragment das statische Feld entryTime definiert, das von den "entry"- und "exit"-Fragmenten verwendet wird.
Klicken Sie im Probekit Editor auf das Element Probe, um dieses Element zu einer Sonde hinzuzufügen. Der Editor zeigt ein Feld an, in dem Sie wie folgt den Java-Code für das FragmentAtClassScope eingeben können:
static long entryTime; static final long thresholdDuration = 100;
entryTime = System.currentTimeMillis();
long now = System.currentTimeMillis(); if ((now - entryTime) > thresholdDuration) { System.out.println( "[Lange Verweildauer in " + className + "." + methodName + ": this=" + thisObject + "]"); }
Beim Eintritt in die Methode erfasst diese Sonde die aktuelle Zeit. Beim Austritt aus der Methode vergleicht die Sonde die aktuelle Uhrzeit mit der erfassten Eintrittszeit. Ist mehr als eine bestimmte Zeit verstrichen (die in "thresholdDuration" angegeben wurde), gibt die Sonde in System.out einen Bericht aus.
Die gerade beschriebene Sonde kann nicht für (direkt oder indirekt) rekursive Methoden verwendet werden. Sie ist auch nicht für Methoden geeignet, die in mehreren Threads gleichzeitig ausgeführt werden können. Das Rekursionsproblem könnten Sie lösen, indem Sie die Eintrittszeiten in einem Stack erfassen. Zur Lösung des Problems mehrerer Threads könnten Sie den Stack in einer Variablen ThreadLocal speichern.
Erforderliche Schritte für das Erstellen einer Sondenversion, die auch für rekursive Methoden mit mehreren Threads geeignet ist:
static ThreadLocal tl = new ThreadLocal() { public Object initialValue() { return new Stack(); } }; static long thresholdDuration = 100; // Meldung, wenn Zeit über 100 ms liegt
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( "[Lange Verweildauer in " + cName + "." + mName + ": this=" + thisObj + "]"); }
Setzen Sie das Lernprogramm mit Übung 1.5: Laufzeitbibliothek für komplexere Sondenlogik verwenden fort.