代码之家  ›  专栏  ›  技术社区  ›  mike g

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

  •  6
  • mike g  · 技术社区  · 14 年前

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

    有没有办法强制验证 全部的 客户机代码和API代码之间的链接?其目的是验证客户机代码是否能够与给定版本的API一起工作,即使它是针对另一个版本编译的。

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

    6 回复  |  直到 14 年前
        1
  •  1
  •   Community kfsone    7 年前

    由于语言的性质和JVM的实现,很难对链接进行强制验证。

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

    当JVM执行与 method invocation instructions . 通常在这一点上 final pass of the JVM's bytecode verifier 被踢入,这可能导致链接错误。不用说,从性能的角度来看,这是昂贵的。

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

        2
  •  0
  •   gtrak    14 年前

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

        3
  •  0
  •   Benoit Courtine    14 年前

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

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

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

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

        4
  •  0
  •   ddimitrov    14 年前

    为了满足您的需要,您可以使用类似于JarJarDiff[1]的工具来获得新版本和旧版本API jars之间的差异。然后将任务转换为验证您没有使用任何不兼容的API。虽然不是自动的,但这种方法会引起您对更改的注意,而不仅仅是对二进制兼容性的注意。

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

    [一] http://depfind.sourceforge.net/tasks/jarjardiff.html

        5
  •  0
  •   Community kfsone    7 年前

    从中汲取灵感 this question Alfresco Wiki ,您可以尝试 -Xcomp 启动测试JVM并预编译类以检查是否存在链接错误。

        6
  •  0
  •   Ian Robertson    14 年前

    我建议使用字节码工具(如asm)来“访问”代码,并让访问者重写 visitMethodInsn . 然后在所有者类上使用反射来查找具有指定名称和签名的方法。您还需要查看调用指令的操作码-它将是invokevirtual、invokeinterface、invokeSpectial和invokestatic之一。注意invokevirtual和invokeinterface之间的区别;调用invokevirtual will 成功调用接口方法,调用invokeinterface将 成功调用未在接口上定义的方法。