在Java中创建堆栈跟踪 [英] Forging a stack trace in Java

查看:206
本文介绍了在Java中创建堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您在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有方法 getStackTrace() 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中创建堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆