PHP会插入代码,这意味着每次运行程序时,它都会在源代码上运行。这样做的好处是,在读取代码时会爆炸(这使得行号打印输出变得微不足道);但是,在其他方面,它通常很昂贵,因为您无法进行深度优化(或进行任何运行时前错误检查)。
Java将其代码编译为一种名为“字节码”的JVM汇编语言。这意味着正在运行的内容通常无法访问(甚至不使用)源代码。也就是说,有技术。编译后的Java类能够添加“额外数据”,其中一个“额外数据元素”是行号表,它是一个索引,允许运行程序集的人在编译器记录时“查找”行号。
这通常可以正常工作,并考虑到:编译器通常不会标记每个指令,源代码可能不可用,优化可能会使某些内部代码块无法以方便指向输入代码文本的方式运行。
代码覆盖率工具如何“修复”这一点,即它们通常会在代码中(在程序集级别)插入大量命令,这些命令有效地充当记录语句的格式,该格式允许工具确定实际遵循代码的路径。然后,它尽可能通过行号表映射回去,然后用于突出显示原始源文件中的行。
如果你想要一些分辨率更精细的东西(可以处理一条线的哪一部分被执行),那么你需要更深入地挖掘。最终,您甚至可以考虑编写自己的编译器(或编译器扩展),它将存储您自己的自定义行号表,以克服当前解决方案的缺点。
像抛出异常(正如Shiven所提到的)和解析行号这样的技巧确实有效;但是,它们会污染您的代码,对实际上不是异常的项目进行奇怪的异常处理,只是为了“获取行号”。由于代码混乱和异常的运行时性能通常较差,我倾向于避免这样的解决方案(但它们确实有效)。
无论如何,希望这能给你一个观点,为什么它并不总是以与PHP完全相同的方式工作。