已执行java代码的日志行号

已执行java代码的日志行号,java,php,code-coverage,Java,Php,Code Coverage,我正在编写一个PHPWeb应用程序的一部分(将在高中的bug查找比赛中使用),其中用户必须在给定的Java程序中查找bug。作为其中的一部分,当Java程序执行时,我们希望突出显示执行代码的Java程序源代码行。要做到这一点,我们只需要已执行的源代码的行号,即代码路径(或者称为代码覆盖率?)。我们将使用行号突出显示源文件中的行 我们将使用PHP的shell-exec()来执行Java程序和获取代码路径的工具(不管是什么)。获取代码路径行号的最简单方法是什么 多谢各位 这是一张描述我们想要什么的图

我正在编写一个PHPWeb应用程序的一部分(将在高中的bug查找比赛中使用),其中用户必须在给定的Java程序中查找bug。作为其中的一部分,当Java程序执行时,我们希望突出显示执行代码的Java程序源代码行。要做到这一点,我们只需要已执行的源代码的行号,即代码路径(或者称为代码覆盖率?)。我们将使用行号突出显示源文件中的行

我们将使用PHP的shell-exec()来执行Java程序和获取代码路径的工具(不管是什么)。获取代码路径行号的最简单方法是什么

多谢各位

这是一张描述我们想要什么的图片


如果使用-g选项编译程序,执行printStackTrace(),捕获跟踪输出并从中提取行号,则可以获得行号。

PHP解释代码,这意味着每次运行程序时它都会在源代码上运行。这样做的好处是在读取代码时放大(这使得行号打印输出变得微不足道);然而,它在其他方面通常是昂贵的,因为您无法深入优化(或执行任何运行前错误检查)

这意味着正在运行的程序通常无法访问(甚至无法使用)源代码。也就是说,有一些技巧。编译后的Java类能够添加“额外数据”,其中一个“额外数据元素”是,这是一个索引,允许运行程序集的人在编译器记录行号时“查找”行号

这通常可以正常工作,但需要考虑的是:编译器通常不会标记每条指令,源代码可能不可用,优化可能会使某些内部代码块无法以便于指向输入代码文本的方式工作

代码覆盖率工具如何“修复”这是因为它们通常在代码中(在程序集级别)插入大量的命令,这些命令有效地充当日志语句,其格式允许工具确定实际遵循的代码路径。然后通过行号表将其映射回尽可能好的位置,然后用于高亮显示原始源文件中的行

如果您想要分辨率更高的东西(可以处理执行的行的哪一部分),那么您需要深入挖掘。最后,您甚至可以考虑编写自己的编译器(或编译器扩展),它将存储您自己的自定义行号表,克服当前解决方案的缺点。p> 抛出异常(正如Shiven提到的)和解析行号这样的技巧确实有效;然而,它们会通过对真正不例外的项目进行奇怪的异常处理来污染代码,只是为了“获取行号”。由于代码混乱和异常的运行时性能通常较差,我倾向于避免此类解决方案(但它们确实有效)


无论如何,希望这能让您了解为什么它不总是以与PHP完全相同的方式工作。

看看Cobertura。它计算覆盖率和类似的东西,如果它还没有这样做,那么将收集的行号添加到其中应该相对容易。
这是一个非常黑客的尝试,但它太慢了,您可能无法在生产中使用它

我从未做过或见过类似的事情,但它确实看起来像一个有趣的问题。我的想法是使用来运行代码,而不仅仅是
java
命令

您可以逐行遍历代码(通过jdb中的
step
命令),每次执行一行时,都会吐出它的行号。这需要PHP方面的一些帮助(它必须解析行号并执行下一步命令),但行号就在那里。下面是一个非常基本的java程序的示例输出

Java(TestClass.Java)

jdb(运行
javactestclass.java
后的jdbtestclass)


请尝试参考此链接

您可以尝试访问程序计数器的值,然后将其映射到lineNumberTable。 或
我认为JVMDI有一种方法可以访问执行代码的行号。我不确定后者,请参考上面的链接,希望它能有所帮助。

如果您真的想在不引发异常的情况下喜欢行号,您可以编写自己的
ClassLoader
,这将为您提供获取行号表的工具;但是,您可能还需要将自己的扩展编写到
Thread
,以便为当前的JVM字节码指令提供一个可用的接口。这是可行的,因为异常抛出已经为您做到了这一点,但是对于不同结构的日志记录通常不需要的东西,这是一项大量的工作。谢谢!我确实理解编译语言和解释语言之间的区别,并且知道获取已执行Java(或任何编译语言)的行号并不简单。我已决定与科贝图拉一起编写报告。我以前从未使用过代码覆盖工具,所以这需要我花一段时间才能弄清楚。请参阅本文下面的评论。非常感谢您的帮助。非常感谢!我一直在看科贝图拉,它似乎做了我希望它做的事情。我们需要的行号位于xml文件中,因此我们可以对其进行解析。但是我很难让它通过命令行运行Java程序。生成指令、运行和报告的代码路径的顺序也是如此吗?我尝试了一下,它生成了代码路径,但它显示程序从未运行过(所有的行都是红色的)。生成此文件的步骤是什么?我只能向您指出有关此文件的cobertura文档:。哟
public class TestClass {
   public static void main(String[] args) {
      System.out.println("foo");
      System.out.println("bar");
   }
}
Initializing jdb ...
> stop at TestClass:3
Deferring breakpoint TestClass:3.
It will be set after the class is loaded.
> run
run TestClass
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> 
VM Started: Set deferred breakpoint TestClass:3

Breakpoint hit: "thread=main", TestClass.main(), line=3 bci=0
3          System.out.println("foo");

main[1] step
> foo

Step completed: "thread=main", TestClass.main(), line=4 bci=8
4          System.out.println("bar");

main[1] step
> bar

Step completed: "thread=main", TestClass.main(), line=5 bci=16
5        }

main[1] step
> 
The application exited