使用Eclipse我可以设置断点并在调试视图上查看当前堆栈跟踪:
但是当我使用Thread.currentThread().getStackTrace()
检查堆栈跟踪时,我得到的信息并不完全相同。例如,所选元素为JUnitTestClassReference
,并且堆栈跟踪中的相关元素(在破折号内)为JUnit4TestReference
(其超类,可能是因为run
方法未被子类覆盖)。
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
org.junit.runners.ParentRunner$3
org.junit.runners.ParentRunner$1
org.junit.runners.ParentRunner
org.junit.runners.ParentRunner
org.junit.runners.ParentRunner$2
org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks
org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks
org.junit.runners.ParentRunner
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
---- org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference ----
org.eclipse.jdt.internal.junit.runner.TestExecution
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner
答案 0 :(得分:2)
堆栈记录代码正在等待返回的调用,而不是对象。如果方法在超类中并且子类没有覆盖它,则堆栈将记录超类方法,因为控件必须最终返回。
获取所涉及对象的运行时类的唯一方法是检查激活帧中this
引用对该方法的特定调用的值。调试器可以向您展示,但是从Java本身那里获取它并不是一种非常简单的方法,您必须使用JDI这样的调试接口。
请注意,还有另一项挑战:StackTraceElement
报告类名称,而不是类对象。由于ClassLoader
的工作方式,同一个VM中可以有两个具有相同名称的类,而StackTraceElement
并没有为您提供足够的信息来区分它们。 (这就像Tomcat这样的容器可以为同一个VM中的两个不同应用程序加载同一个库的两个不同版本。)
答案 1 :(得分:1)
StackTraceElement
不会引用所涉及的实际对象,只会引用类。我可以想出为什么这实际上是一个好主意的一些原因,至少是StackTraceElement
的可序列化。
StackTraceElement
中的类引用被定义为引用类声明方法,而不是发生异常时保存方法的当前对象的类。这可能是因为您可以将超级实现与重写实现区分开来。因此,只有异常后的堆栈跟踪既不能获得实际的对象,也不能获得实际的子类。(
Eclipse(以及其他调试器接口)向您显示程序运行时的实时跟踪。您正确地注意到此实时信息是通过JPDA获得的。
Java调试接口(JDI)可以访问表示为StackFrame
的实时堆栈帧信息,其中实际对象可用:
ObjectReference thisObject()
返回当前帧的'this'值。 “this”的ObjectReference仅适用于非本机实例方法。
答案 2 :(得分:0)
当我遇到同一问题,并且想知道如何做到这一点时,也许这对以后的参考很有帮助
您可以使用以下方法从StackTraceElement
中获取方法对象:
//replace with your StackTraceElement
StackTraceElement method_obj = Thread.currentThread().getStackTrace()[0]
Class<?> object_context = Class.forName(method_obj.className)
Method method = object_context.getMethod(method_obj.methodName, null)