PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [JAVA] aufrufende Klasse bzw. Methode bestimmen


Wanginator
2007-11-03, 23:37:22
Hallo,

ist es möglich in Java in einer Methode die aufrufende Klasse und aufrufende Methode zu bestimmen? Also folgendes


public void foo() {
// jetzt ausgeben welche Klasse mich aufgerufen hat und welche Methode dieser Klasse
}


Das wäre sehr hilfreich für mich zum Loggen.

Der_Donnervogel
2007-11-04, 00:56:53
Ja sowas kann man machen. Keine Ahnung ob es noch eine elegantere Methode gibt, aber folgendes sollte funktionieren:
Exception ex = new Exception();
StackTraceElement s = ex.getStackTrace()[1];
System.out.println("Aufrufende Klasse: " + s.getClassName());
System.out.println("Aufrufende Methode: " + s.getMethodName());

Bietchiebatchie
2007-11-04, 02:40:29
Das funktioniert aber nur garantiert fehlerfrei solange du das ganze als debug ausführst. Bei einer normalen optimierten Version kannst du dir absolut nicht sicher sein, wie dein Stack aussieht.

HellHorse
2007-11-04, 15:21:08
Das wäre sehr hilfreich für mich zum Loggen.
Was wohl der Grund dafür ist, dass jedes halbwegs brauchbare logging framework von der Stange die Klasse mit loggt. Wenn du die Methode umbedingt brauchst, kannst du ja einen Aspekt drumbasteln, dann bist du voll buzzword kompatibel.

Der_Donnervogel
2007-11-04, 21:14:44
Das funktioniert aber nur garantiert fehlerfrei solange du das ganze als debug ausführst. Bei einer normalen optimierten Version kannst du dir absolut nicht sicher sein, wie dein Stack aussieht.
Die Frage ist es wie wahrscheinlich ist es, dass der StackTrace nicht stimmt.

Sicher steht im JavaDoc zu der Funktion getStackTrace() drinn, dass die abhängig von der VM unter gewissen Umständen, nicht den kompletten StackTrace zurückliefert. Bisher ist mir das aber so viel ich mich erinnern kann noch nie vorgekommen, daß bei einer Exception der StackTrace nicht gestimmt hat. Die Methodenaufrufe mitloggen zu wollen, hört sich aber sehr nach einer Testversion an, denn in einer Releaseversion macht das meiner Meinung nach wenig Sinn.

Bietchiebatchie
2007-11-04, 21:26:36
Naja ich denke mal wenn man z.B. eine simple Getter-Funktion aufruft, ist die Wahrscheinlich relativ hoch, dass das ganze geinlined wird und damit hast du dann beim "Aufruf" der GetterFunktion eben nicht den Stack der Getter-Funktion sondern den der vorherigen Funktion. Allerdings kann es auch sein, dass sich die VM um sowas kümmert; das war mehr ein prinzipieller Einwurf von mir, dass man sich nicht darauf verlassen sollte, was auf dem Stack liegt.

Abgesehen davon wüßte ich auch nicht, dass es sonst eine Methode gäbe, um festzustellen wo die Methode aufgerufen wurde.

Monger
2007-11-04, 22:19:05
Blöde Frage, aber GIBT es im Byte Code überhaupt noch Methoden?

Ich dachte, da wäre letztendlich auch alles in Sprung Befehle aufgelöst :confused:

Der_Donnervogel
2007-11-05, 10:58:44
Allerdings kann es auch sein, dass sich die VM um sowas kümmert; das war mehr ein prinzipieller Einwurf von mir, dass man sich nicht darauf verlassen sollte, was auf dem Stack liegt.
Der Einwand war auch berechtigt. Ich habe allerdings vorausgesetzt, dass der Grund für diesen Thread wohl in Richtung Fehlersuche, oder vielleicht Performanceanalyse gehen wird. Für so einen Anwendungszweck ist die Art an die Aufrufende Methode zu kommen aber meiner Meinung nach ausreichend sicher und auch schnell umgesetzt.
Abgesehen davon wüßte ich auch nicht, dass es sonst eine Methode gäbe, um festzustellen wo die Methode aufgerufen wurde.
Falls mit "Methode", eine andere von Java bereitgestellte Funktionalität gemeint ist, so weiß ich auch keinen anderen Weg. Eventuell lässt sich mit Reflection etwas machen. Falls mit "Methode" eine grundsätzliche Möglichkeit das umzusetzen gemeint war, so gäbe es schon Alternativen. Beispielsweise die angesprochenen Aspekte (falls man eine passende Umgebung hat), oder aber indem man beispielsweise die zu loggenden Funktionen überschreibt und ihnen einen extra Parameter verpasst, bei dem die aufrufende Funktion sich übergibt. So kann man loggen, und dann den Aufruf weiterleiten, ohne die eigentliche Funktion ändern zu müssen.
Blöde Frage, aber GIBT es im Byte Code überhaupt noch Methoden?

Ich dachte, da wäre letztendlich auch alles in Sprung Befehle aufgelöst :confused:
Also der Code wird auf jeden Fall umgeschrieben und meines Wissens werden beispielsweise for-Schleifen in gotos aufgelöst. Es könnte aber sein, dass Methoden erhalten bleiben, denn irgendwie muss Java ja auch Reflection umsetzen und dort kann man ja sehr dynamisch mit Methoden arbeiten, sodass irgendwelche Informationen auch im Bytecode vorhanden sein müssen.

Achill
2007-11-07, 22:35:58
Thread.currentThread().getStackTrace() ist dein Freund ...


/**
* @author Achill
* @version 1.0.0
*/
public class MainStack {

public static void main(String[] args) {

for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
System.out.println(stackTraceElement);
}
}
}


ergibt das:


java.lang.Thread.getStackTrace(Thread.java:1426)
MainStack.main(MainStack.java:9)


Ignoriert man das erste StackTraceElement, so bekommt man den aktuellen StackTrace...

Das zeigt aber auch gleichzeitig das Problem auf, dass man nur den StackTrace im aktuellen Thread bekommen kann.

Ansonsten hilft nur: Thread.getAllStackTraces()