Ja, es ist möglich, den Stack-Trace zu manipulieren. Wie gesagt, es hängt davon ab, wo Sie das Problem angreifen wollen (und können).
Ein Beispiel:
Bei einem Protokoll für entfernte Methodenaufrufe, das ich für unser Projekt implementiert habe, fangen wir im Falle einer Exception diese auf der Zielseite ab, schneiden die unteren StackTraceElemente ab (die immer gleich sind, bis zum eigentlichen Aufruf der Zielmethode mit Reflection), und senden die Exception mit dem wichtigen Teil des Stack Trace an die Aufruferseite.
Dort rekonstruiere ich die Exception mit ihrem (gesendeten) Stacktrace, und füge ihn dann mit dem aktuellen Stacktrace zusammen. Dazu entfernen wir auch die obersten Elemente des aktuellen Stacktrace (die nur Aufrufe des Remote-Call-Frameworks enthalten):
private void mergeStackTraces(Throwable error)
{
StackTraceElement[] currentStack =
new Throwable().getStackTrace();
int currentStackLimit = 4; // TODO: raussuchen
// We simply cut off the top 4 elements, which is just
// right for our framework. A more stable solution
// would be to filter by class name or such.
StackTraceElement[] oldStack =
error.getStackTrace();
StackTraceElement[] zusammen =
new StackTraceElement[currentStack.length - currentStackLimit +
oldStack.length + 1];
System.arraycopy(oldStack, 0, zusammen, 0, oldStack.length);
zusammen[oldStack.length] =
new StackTraceElement("",
"<remote call %" +callID+ ">",
"", -3);
System.arraycopy(currentStack, currentStackLimit,
zusammen, oldStack.length+1,
currentStack.length - currentStackLimit);
error.setStackTrace(zusammen);
}
Das ergibt zum Beispiel diese gedruckte Spur:
java.lang.SecurityException: The user example does not exist
at de.fencing_game.db.userdb.Db4oUserDB.login(Db4oUserDB.java:306)
at de.fencing_game.server.impl.StandardServers$SSServer$1.run(StandardServers.java:316)
at de.fencing_game.server.impl.StandardServers$SSServer$1.run(StandardServers.java:314)
at java.security.AccessController.doPrivileged(Native Method)
at de.fencing_game.server.impl.StandardServers$SSServer.login(StandardServers.java:313)
at de.fencing_game.transport.server.ServerTransport$ConnectionInfo$4.login(ServerTransport.java:460)
at .<remote call %2>()
at $Proxy1.login(Unknown Source)
at de.fencing_game.gui.basics.LoginUtils.login(LoginUtils.java:80)
at de.fencing_game.gui.Lobby.connectTo(Lobby.java:302)
at de.fencing_game.gui.Lobby$20.run(Lobby.java:849)
In Ihrem Fall wäre es natürlich besser, wenn Sie einfach Ihr Array durchlaufen, die wichtigen Elemente in eine Liste kopieren und diese dann als neue stackTrace festlegen. Stellen Sie sicher, dass Sie dies auch für die Ursachen (d.h. verknüpfte Throwables) tun.
Sie können dies im Konstruktor Ihrer Ausnahmen tun, oder dort, wo Sie die Stack Traces ausgeben, oder irgendwo dazwischen (wo Sie die Ausnahme abfangen, manipulieren und erneut auslösen).