问题描述
当您在Java中使用RMI时,将收到异常的远程堆栈跟踪将在您收到之前,稍后如下:
When you use RMI in Java the remote stack trace of an exception will be prepended when you receive it, somewhat like this:
ERROR Client received error when doing stuff:
myapp.FooBarException: bla
at server.myMethod()
at rmi.callHandler() // and now, on the next line comes the client
at rmi.sendCall();
at client.doServerMethod()
at Thread.run()
如何这种堆栈跟踪伪造是否完成?
How is that kind of stacktrace "forgery" done?
我想要什么(除了被感兴趣)那么这样可以帮助我,如果我能做到这一点:
What do I want it for (apart from just being iterested)? Well, it would help me if I could do this:
outer() {
thread = new Thread(...
inner();
// inner() throws
// RuntimeException
// at inner();
// at Runnable.run();
// at Thread.run();
// at outer();
// at lalalala();
// ...
).start();
thread.join();
}
并使其在 inner()
将在堆栈跟踪中具有 outer()
(以及链中的方法),以便记录目的。 / p>
And make it so that an exception thrown in inner()
would have outer()
(and methods lower down the chain) in the stacktrace as well, for logging purposes.
推荐答案
这很简单:
Throwable有方法和 setStackTrace()
。
Throwable has methods getStackTrace()
and setStackTrace()
.
从(非开源,但也许我有一天会打开远程调用引擎):
From one of my projects (non open-source, but maybe I'll some day open the remote call engine):
/**
* Setzt den Stack-Trace zusammen. Das untere Ende (tiefer in der
* Aufrufhierarchie, am Anfang des Arrays/der Ausgabe) ist das,
* welches im Throwable schon drin ist, das obere Ende wird aus
* dem aktuellen Stack genommen. Dazwischen
* kommt ein "Remote-Aufruf-Markierer".
*/
为方便起见翻译:
private void mergeStackTraces(Throwable error)
{
StackTraceElement[] currentStack =
new Throwable().getStackTrace();
int currentStackLimit = 5; // TODO: raussuchen
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);
}
(在服务器端,我已经切断了堆栈跟踪与方法调用本身无关,即与消息处理相关的所有内容。)
(On the server side, I'm already cutting off the parts of the stack trace which do not relate to the method call itself, i.e. everything related to the message handling.)
这将产生一个如下所示的组合堆栈跟踪:
This results in a combined stack trace like this:
java.lang.SecurityException: Das Passwort für Nutzer »Paul« ist falsch.
at de.fencing_game.db.userdb.Db4oUserDB.login(Db4oUserDB.java:304)
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)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:647)
at java.awt.EventQueue.access$000(EventQueue.java:96)
at java.awt.EventQueue$1.run(EventQueue.java:608)
at java.awt.EventQueue$1.run(EventQueue.java:606)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:617)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
我想RMI系统做的事情非常相似(只是没有════════════════════════= / code>)。
I suppose the RMI system does something quite similar (just without the ══════════════════════════
).
编辑:
对于您的用户当内线启动时,您必须保存外线程的堆栈跟踪,然后在run方法中捕获异常,并将外部堆栈跟踪附加到内部异常的堆栈跟踪。我真的建议你放一些类型的分隔符。
For your usecase, you would have to save the stack trace of the outer thread when the inner thread is started, then in the run method catch the exception and append the outer stack trace to the stack trace of the inner exception. I would really recommend putting some type of separator, though.
这篇关于在Java中创建堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!