从堆栈跟踪元素中获取实际的类

时间:2015-06-08 18:42:04

标签: java debugging reflection stack-trace

使用Eclipse我可以设置断点并在调试视图上查看当前堆栈跟踪:

enter image description here

但是当我使用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
  • 有没有办法获得子类名?
  • 如果没有,Eclipse如何获得它(可能使用JPDA)?

3 个答案:

答案 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)