提问者:小点点

JVM什么时候会在堆栈跟踪中省略行信息?我如何防止它?


我有一个非常令人困惑的情况:

我有一个使用行信息编译的类(使用 javap -l 验证)。此类使用 ASM 加载和检测。我验证了是否加载了正确的类(即不是来自其他地方的过时类文件)。我还确保未设置 ASM 标志ClassReader.SKIP_DEBUG。现在,如果我调用 Thread.currentThread().getStackTrace(),我会得到关于这个缺少行信息的类的 StackTraceElement。在 Eclipse 中进行调试时,行信息显示在堆栈跟踪中。我还确保 JVM 以 -Xint 启动,以确保在对代码进行 JIT 编译时不会将信息作为优化删除。

最令人困惑的是:尽管所有类的加载和检测都是一样的,但这只适用于某些类,而不是所有类。这就是我认为这与JVM有关的主要原因。

所以我的问题是:JVM 是否在堆栈跟踪中省略了行信息,如果是这样,我何时以及如何防止这种情况?

编辑:只是为了弄清楚:这是我面前的源文件的类文件,而不是第三方库的类文件。从上面应该清楚,我努力确保信息在字节码中。

编辑:现在我甚至发现了一个例子,其中一个<code>StackTraceElement</code>有行号信息,而另一个没有,并且它们涉及来自同一类的不同方法!


共3个答案

匿名用户

我想知道堆栈跟踪中报告的行(或者没有报告)是在ASM检测类时生成的。由于它们是在编译后修改的,所以任何行号都不会出现在类文件中,因此类加载器无法使用它们(或者javap无法报告它们)。我在运行时代码生成方面没有太多经验,所以这只是一个猜测,但也许你可以考虑一下。

匿名用户

这与类文件是如何编译的有关。在这里看一眼:

http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/javac.html

并在-g标志周围寻找“调试信息”。如果您添加-g,您的代码将包含行号(和许多其他有用的信息)。

恐怕这不会向第三方库追溯添加调试信息。您必须了解如何从供应商那里获得源代码或调试构建。我发现这通常是没有必要的。

匿名用户

并非所有行号在 JVM 中都可用。一些第三方库可能在没有行号的情况下编译,特别是非开源库,甚至一些Java类都有受保护的源代码,这些源代码正在进行加密或其他一些受保护的逻辑。简而言之,并非所有内容都始终具有行号。