【问题标题】:Maximum size of a method in Java 7 and 8Java 7 和 8 中方法的最大大小
【发布时间】:2013-07-02 09:51:06
【问题描述】:

我知道使用 Java 的方法不能超过 64 KB。该限制导致我们从JavaCC 语法生成的代码出现问题。我们在使用 Java 6 时遇到了问题,并且能够通过更改语法来解决这个问题。 Java 7 的限制是否已更改,还是计划为 Java 8 更改?

只是为了说清楚。我自己不需要大于 64 KB 的方法。但是我写了一个语法,可以编译成一个非常大的方法。

【问题讨论】:

  • 当我试图编译一个巨大的brainf**k代码时,我遇到了同样的问题。
  • 鉴于没有相反的信息,我认为可以安全地假设这个限制仍将在 Java 8 中强制执行......当然,另一个(昂贵的)选择可能是更改语法parboiled 的引擎,它允许您用纯 Java 编写语法。
  • 看看this的文章
  • 我个人认为创建这么大的方法是一个JavaCC 中的错误。它确实应该能够传播其代码。特别是考虑到 JVM 绝对不是为优化如此庞大的方法而构建的。

标签: java java-7 java-8


【解决方案1】:

根据JVMS7

end_pc 是独占的这一事实是历史上的错误 Java虚拟机的设计:如果Java虚拟机代码 一个方法的长度正好是 65535 字节,并以一条指令结束 即 1 字节长,则该指令不能被 异常处理程序。编译器编写者可以通过以下方式解决此错误 限制生成的 Java 虚拟机代码的最大大小 对于任何方法、实例初始化方法或静态初始化器 (任何代码数组的大小)为 65534 字节。

但这是关于Java 7Java 8 没有最终规范,因此没有人(除了它的开发人员)可以回答这个问题。

UPD (2015-04-06) 根据JVM8Java 8 也是如此。

【讨论】:

  • Java 中真的有这么一个“bug”还没有修复吗?可能是一个严重的限制,特别是对于 LaurentG 的情况。
  • @Fire-Dragon-DoL 引用的讨论只是关于该方法的长度必须少一个字节。这是相当无关紧要的。限制不是由于任何简单的“错误”造成的:它存在于字节码的整体设计中,要修复它需要重新指定它。
【解决方案2】:

好问题。一如既往,我们应该去the source寻找答案("The Java® Virtual Machine Specification")。该部分没有明确提到限制(如 Java6 VM 规范一样),但有些谨慎:

在调用方法(第 2.6 节)时创建的框架的局部变量数组中的最大局部变量数被 Code 属性(第 4.7.3 节)的 max_locals 项的大小限制为 65535,给出了方法的代码,以及Java虚拟机指令集的16位局部变量索引。

干杯,

【讨论】:

  • “最大数量的局部变量”恰好具有相同的数值,但与 OP 要求的“方法的最大大小”仍然完全不同。
【解决方案3】:

它没有改变。在 Java 7 和 Java 8 中,方法中的代码限制仍然是 64 KB。

参考资料:

  1. 来自 Java 7 虚拟机规范 (4.9.1 Static Constraints):

类文件中 Java 虚拟机代码的静态约束指定如何 Java 虚拟机指令必须放在代码数组中,而 单个指令的操作数必须是。

代码数组中指令的静态约束如下:

  • 代码数组不能为空,所以code_length项不能有 值 0。
  • code_length 项的值必须小于 65536。
  1. 来自 Java 8 虚拟机规范 (4.7.3 The Code Attribute):

code_length 项的值给出了代码数组中的字节数 对于这种方法。

code_length 的值必须大于零(因为代码数组必须 不能为空)且小于 65536。

【讨论】:

    【解决方案4】:

    Andremoniy 已经回答了这个问题的java 7 部分,但当时似乎很快就决定了java 8,所以我完成了涵盖该部分的答案:

    引用jvms:

    end_pc 是排他性的这一事实是 Java 虚拟机设计中的一个历史错误:如果 Java 虚拟机的方法代码正好是 65535 字节长并且以 1 字节长的指令结束,那么该指令不能由异常处理程序保护。编译器编写者可以通过将任何方法、实例初始化方法或静态初始化程序(任何代码数组的大小)生成的 Java 虚拟机代码的最大大小限制为 65534 字节来解决此错误。

    正如你所见,这个历史问题似乎至少在这个版本(java 8)中没有得到解决。

    【讨论】:

      【解决方案5】:

      作为一种解决方法,如果您可以访问解析器的代码,您可以修改它以在 JVM 编译器施加的任何“限制”内工作...... (假设不需要永远在解析器代码中找到要修改的部分)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-18
        • 2023-03-30
        • 1970-01-01
        • 2015-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多