Java “Einsichten”
Manchmal ist es nützlich wenn ein Programm zur Laufzeit über sich selbst Bescheid weiss. Mit dem Zugang auf sich selbst kann man Funktionen implementieren, die beim Entwickeln gewisse Abläufe vereinfachen können. Ein Beispiel dafür ist die dynamische Ausgabe des Inhalts der Struktur eines Objekts zur Laufzeit. Das kann zu Debugging Zwecken nützlich sein, wenn kein Debugger vorhanden ist, zum Beispiel auf einem Server. Um auf die Felder eines Objekts zugreifen zu können verwendet man
Field[] myFields = this.getClass().getDeclaredFields();
um auf die Methoden eines Objekts zugreifen zu können verwendet man
Method[] myMethods = this.getClass().getMethods();
wobei this durch eine beliebige Klasse ersetzt werden kann. Java verbietet es von Haus aus auf private Felder zugreifen zu können. Jedoch kann mit der Methode setAccessible(true) der Zugriff erlaubt werden. Mit diesen Werkzeugen an der Hand ist es nun ein Leichtes eine Methode zu schreiben, welche zur Laufzeit den Inhalt jedes beliebigen Objekts ausgeben kann.
Eine weitere interessante “Einsicht” ist die Rückverfolgbarkeit, von welcher Funktion aus eine Funktion aufgerufen wurde. Meinem Wissensstand nach gibt es leider in Java kein Bordmittel um auf diese Information zuzugreifen. Allerdings gibt es einen “Hack” um das zu bewerkstelligen. Jedesmal wenn eine Funktion aufgerufen wird, dann legt Java ein Element mit diversen Informationen, darunter auch den Namen der Funktion, auf seinen internen Verwaltungsstack. Wird die Funktion verlassen wird das Stackelement wieder vom Stack genommen. Dadurch ist zum Beispiel die Funktion printStackTrace() zur Ausgabe von StackTraces bei Exceptions möglich. Schaut man sich den Stack an, dann sieht man in welcher Reihenfolge Funktionen aufgerufen wurden. Diesen Umstand machen wir uns zum Nutzen und generieren in einer Funktion eine Standard-Exception. Diese beinhaltet natürlich den Stack zum Zeitpunkt zu dem die Exception generiert wrude.
Mit StackTraceElement stackElement = myException.getStackTrace()[n] greift man dann auf das n-te Element des Stacks zu. Um auszugeben welche Funktion die Funktion, in welcher die Exception erzeugt wurde, aufgerufen hat, wäre das das 1te Element also getStackTrace()[1]. Um den Namen einer Funktion auszugeben ruft man dann auf dem StackTraceElement die Funktion getMethodName() auf.
Durch die beiden oberen “Einsichten” lassen sich einige Funktionalitäten generalisieren und in eigene Klassen auslagern um bei Bedarf wieder darauf zuzugreifen. Zugegebenermassen ist die Methode über Exceptions auf den Stack zuzugreifen etwas dirty, funktioniert aber wunderbar und ermöglicht Funktionen die unnötige Tiparbeit ersparen. Ich zum Beispiel verwende diese Funktion zum Profiling und weiss dadurch immer welche Funktionen davon betroffen sind.

