【问题标题】:Method Order in generated class file by javacjavac生成的类文件中的方法顺序
【发布时间】:2012-12-24 09:01:34
【问题描述】:

在 JDK7 中,反射 API 发生了变化,现在 getDeclaredMethods() 返回的方法按照它们在源文件中声明的顺序返回。

现在我的问题是,javac 生成的 .class 文件是否包含方法与它们在源文件中定义的顺序相同,或者它也可以按随机顺序编写方法? p>

【问题讨论】:

  • 您可以通过再次编译和查看反编译代码(使用反编译器)轻松检查自己
  • @vishal_aim - 是的,我已经做到了,对我来说也是如此。我更想知道它是否会发生在不同的 jdk 实现/平台上。
  • 从纯语言规范的角度来看,声明方法的顺序对程序没有任何影响,所以我看不出改变方法顺序的编译器是如何不合规,因为该程序将以完全相同的方式工作......
  • @assylias:问题是我有一个遗留代码库,其中包含数千个junit,其中一些取决于它们的执行顺序。他们曾经使用 JDK6(因为反射返回的方法与定义的顺序相同),但使用 jdk7 时会间歇性失败。
  • @JoachimSauer:你完全正确。我同意它们的编码很糟糕,长期的解决方案是更正测试用例,但我正在寻找一种更快的解决方案,以使它们现在可以正常工作。

标签: java javac


【解决方案1】:

Binary Compatibility chapter of the Java Language Specification 明确表示允许对类文件中的元素进行重新排序:

[...] 这里列出了 Java 编程语言支持的一些重要的二进制兼容更改:

  • [...]

  • 对现有类型声明中的字段、方法或构造函数重新排序。

  • [...]

  • 重新排序类或接口的直接超接口列表。

这意味着它们出现在 .class 文件中的顺序不受规范的限制。如果您想依赖它,您必须(1)知道您的特定实现使用与定义顺序相同的顺序(测试它,就像您所做的那样,是一个好主意,但不能保证任何事情),或 (2) 自行更改顺序。

【讨论】:

  • “二进制兼容性”确实一定意味着结果完全相同。这仅意味着针对旧版本编译的代码将继续与新版本一起工作(或至少加载/链接)。
  • @JoachimSauer 我接受这一点,但在我看来,可以推断出不同的编译器可以为同一个类生成具有不同方法顺序的类文件......我认为这可以转化为“不受规范规定”。
  • 我同意“非口述”部分,我只是不认为这一章是一个很好的论据。
【解决方案2】:

Class.getDeclaredMethods API 很清楚“...返回的数组中的元素没有排序,也没有任何特定的顺序...”。最可能的原因是 javac 没有义务以任何特定的顺序在 .class 中生成方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多