一般来说,一组代码(客户端代码)链接另一组代码(API代码)。通常在.java和amp;之间验证Java链接。 .class在编译时或.class& .class在运行时。然而,在后一种情况下,验证是在遇到错误引用时(即它是惰性的)。
有没有办法强制验证客户端代码和API代码之间的所有链接与编译代码?目的是验证客户端代码是否可以使用给定版本的API - 即使它已经针对另一个版本进行编译。
(当然,有一种方法是对API进行反编译和重新编译,但是有更直接的方法吗?)
答案 0 :(得分:1)
由于语言的性质和JVM的实现,强制验证链接很困难。
我认为这个问题的基本原理是在运行时防止链接错误,并且这样做的意图非常有效。但是,当从JVM的角度来看待链接错误的原因时,在没有任何性能影响的情况下强制执行验证或多或少都很困难。
当JVM执行与method invocation instructions对应的字节码时,会在运行时抛出链接错误。通常在这一点上,延迟final pass of the JVM's bytecode verifier被踢入,这可能导致链接错误。不用说,从性能的角度来看,这是昂贵的。
(我的假设是)大多数项目(包括商业项目)因此避免强制验证,而是依靠构建和依赖管理系统来避免痛苦。 this SO question中的更多评论;选择OSGi框架的答案可能有所帮助。
答案 1 :(得分:0)
也许您可以对ClassPath中的jar指定的API运行junit测试,然后只为不同版本的api切换jar并再次运行测试。您可以轻松实现自动化。
答案 2 :(得分:0)
可以通过反身性来分析来自java类的代码。请参阅包java.reflect。一些分析工具使用此功能来获取有关已编译代码的信息。最好的例子可能是FindBugs。
这个API作为限制,我认为你不能用它做你想做的事。如果在方法中调用依赖项,则反射API可以找到方法及其参数,但不能为您提供该方法中使用的依赖函数。
所以我认为Java中不存在这样的分析工具。
解决方案是提供一次代码及其所有依赖项。在开发过程中,Maven等生命周期管理工具可以帮助您管理项目的依赖关系。
答案 3 :(得分:0)
根据您的需要,您可以使用像JarJarDiff [1]这样的工具,并获得新旧API版本之间的差异。然后将任务转换为验证您不使用任何不兼容的API。虽然不是自动的,但这种方法会引起您对变化的关注,而不仅仅是二进制兼容性。
如果您只想检查二进制兼容性,最简单的方法是针对新JAR重新编译项目。更困难(更脆弱)是扫描类路径和 调用每个类的每个方法,查找链接异常。请注意,这种天真的方法不会测试所有可能的路径,也没有什么好处。
答案 4 :(得分:0)
从this question和Alfresco Wiki中获取想法,您可以尝试-Xcomp
启动测试JVM并预编译类以检查是否存在链接错误。
答案 5 :(得分:0)
我建议使用字节码工具(如asm)“访问”代码,并让访问者覆盖visitMethodInsn。然后在所有者类上使用反射,查找具有指定名称和签名的方法。您还需要查看调用指令的操作码 - 它将是invokevirtual,invokeinterface,invokespecial和invokestatic之一。注意要注意invokevirtual和invokeinterface之间的区别;对invokevirtual的调用将不成功调用接口方法,并且调用invokeinterface将不成功调用未在接口上定义的方法。