Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何验证已编译Java代码之间的链接?_Java_Dynamic Linking - Fatal编程技术网

如何验证已编译Java代码之间的链接?

如何验证已编译Java代码之间的链接?,java,dynamic-linking,Java,Dynamic Linking,一般来说,一组代码(客户机代码)与另一组代码(API代码)链接。Java链接通常在编译时在.Java和.class之间进行验证,或者在运行时在.class和.class之间进行验证。然而,在后一种情况下,当遇到错误的引用时(即,它是惰性的),验证是一样的 是否有一种方法可以强制使用编译后的代码同时验证客户端代码和API代码之间的所有链接?其目的是验证客户端代码是否能够与给定版本的API一起工作,即使它是根据另一个版本编译的 (当然,一种方法是对API进行反编译和重新编译,但是有更直接的方法吗?也

一般来说,一组代码(客户机代码)与另一组代码(API代码)链接。Java链接通常在编译时在.Java和.class之间进行验证,或者在运行时在.class和.class之间进行验证。然而,在后一种情况下,当遇到错误的引用时(即,它是惰性的),验证是一样的

是否有一种方法可以强制使用编译后的代码同时验证客户端代码和API代码之间的所有链接?其目的是验证客户端代码是否能够与给定版本的API一起工作,即使它是根据另一个版本编译的


(当然,一种方法是对API进行反编译和重新编译,但是有更直接的方法吗?

也许您可以对类路径中jar指定的API运行junit测试,然后只需为不同版本的API切换jar并再次运行测试。您可以很容易地实现自动化。

可以通过自反性分析java类中的代码。看看包裹。一些分析工具使用此功能获取有关已编译代码的信息。最好的例子可能是

这个API是有限制的,我认为你不能用它做你想做的事情。如果在方法中调用依赖项,反射API可以找到该方法及其参数,但不能提供该方法中使用的依赖函数

所以我认为Java中不存在这样的分析工具


解决方案是提供一次代码及其所有依赖项。在开发中,像Maven这样的生命周期管理工具可以帮助您管理项目的依赖关系。

由于语言的性质和JVM的实现,强制验证链接是困难的

我相信这个问题的基本原理是在运行时防止链接错误,这样做的意图非常有效。然而,当我们从JVM的角度来看链接错误的原因时,在没有任何性能影响的情况下强制执行验证或多或少是困难的

当JVM执行对应于的字节码时,在运行时抛出链接错误。这通常是在这一点上,延迟被踢入,这可能会导致链接错误。不用说,从性能的角度来看,这是昂贵的


(我的假设是)大多数项目(包括商业项目)因此避免了强制验证,而是依赖构建和依赖关系管理系统来避免痛苦。更多的评论;选择OSGi框架的答案可能会有所帮助。

对于您所需要的,您可以使用类似于JarDiff[1]的工具,了解API JAR的新版本和旧版本之间的差异。然后,任务被转换为验证您没有使用任何不兼容的API。虽然不是自动的,但这种方法将您的注意力吸引到更改上,而不仅仅是二进制兼容性

如果您只想检查二进制兼容性,最简单的方法是根据新JAR重新编译项目。更困难(更脆弱)的是扫描类路径和 调用每个类的每个方法,查找链接异常。请注意,这种幼稚的方法不会测试所有可能的路径,并且没有什么好处


[1]

借鉴和的思想,您可以尝试启动测试JVM并预编译类以检查是否存在链接错误。

我建议使用诸如asm之类的字节码工具“访问”代码,并让访问者重写。然后对owner类使用反射,查找具有指定名称和签名的方法。您还需要查看调用指令的操作码——它将是invokevirtual、invokeinterface、InvokSpecial和invokestatic中的一个。注意注意invokevirtual和invokeinterface之间的区别;调用invokevirtual不会成功调用接口方法,调用invokeinterface也不会成功调用未在接口上定义的方法。

性能不一定是一个主要问题,因为可以记住结果。另外,在某些情况下,代码量不一定很大。好的,很好。然后,您可能希望使用诸如ASM(参考CheckClassAdapter的使用)或BCEL(其中包含正义验证器)之类的字节码工程库来执行验证(如果它们足够),或者在需要时扩展它们。我不确定Javassist是否有类似的特性。