2011-03-11 43 views
3

我們需要調試一個Java應用程序,它隨機做它不應該做的事情。如何在調用特定Java方法時轉儲堆棧跟蹤?

要了解問題的根源,我們需要得到一個每當一個特定的方法被調用堆棧跟蹤。這聽起來很簡單(在此特定方法中添加Thread.dumpStack()),但是這是來自JDK的代碼類,因此我們並不真正想要混淆它(即使我們確實可以)。

有誰知道,如果我們可以實現JVM中的某種「聽衆」的,將在一個特定的方法被調用檢測並轉儲堆棧跟蹤?

這是一個生產系統,因此,如果解決方案是我們需要有一些對性能的影響非常有限調試器。

謝謝您的輸入。

+1

最簡單的解決方案是修改提到的jdk類..我認爲它不會造成問題.. – 2011-03-11 13:21:50

+1

使用AOP可以將附加的運行時代碼附加到特定的方法。 – anubhava 2011-03-11 13:30:20

回答

0

取決於有多少不同位置的方法是從所謂的,你可以把一個包裝周圍並從包裝中做一個堆棧轉儲。

0

我的東西爲簡單起見,做的是以下行添加到我的代碼

log.info("Method called", new Throwable("HERE")); 
0

而是有問題的類的實例,使用的java.lang.reflect.Proxy一個實例。這允許您在將所有方法調用轉發給實例之前攔截所有方法調用並執行某些操作。

我覺得這是至少1 AOP框架的心臟。

1

「有誰知道,如果我們可以實現某種‘在JVM監聽器’,將檢測當特定方法被調用和轉儲堆棧跟蹤?

這是一個生產系統,因此,如果該解決方案是一個調試器,我們需要對性能影響非常有限的東西。「

這些要求是矛盾的。無論你如何做,傾倒堆棧都很昂貴。海事組織,你真正需要做的是建立一個測試服務器並在那裏運行你的調查。

FWIW,最簡單和可能最便宜的方式做這樣的事情是插入其中的一個作爲方法的第一個語句:

log.info("Method called", new Throwable()); 

    new Throwable("method called").printStackTrace(System.out); 
0

我用這目的是java instrumentation api

與Java儀表API,您可以在運行時修改任何類的字節碼,你可以添加一些代碼(如AOP)。我的github上提供了一個使用javassist在運行時測試java類和方法的示例。

https://github.com/kreyssel/maven-examples/tree/master/javaagent

你可以簡單地修改LoggerAgent.java和刪除記錄語句並添加Thread.dumpStack()

你在生產運行時更改的唯一一件事就是代理jar添加到Java命令行。

-javaagent:jarpath[=options] 

另一篇博文可以閱讀here

2

使用Byteman。它可以很容易地將跟蹤代碼注入正在運行的服務器。我們的支持團隊喜歡它。 http://www.jboss.org/byteman