1. 概述

当 J****ava 方法超过 65535 字节时,我们会收到编译错误“代码太大” 。在本文中,我们将讨论发生此错误的原因以及如何修复它。

2. JVM 约束

Code_attribute 是JVM规范的 method_info 结构中的一个可变长度的表。该结构包含方法的 JVM 指令,该方法可以是常规方法,也可以是实例、类或接口的初始化方法:

Code_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 max_stack;
    u2 max_locals;
    u4 code_length;
    u1 code[code_length];
    u2 exception_table_length;
    {   
        u2 start_pc;
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    }
    exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

属性 code_length 指定方法中代码的长度:

code_length
The value of the code_length item gives the number of bytes in the code array for this method.
The value of code_length must be greater than zero (as the code array must not be empty) and less than 65536.

从上面可以看出, JVM规范规定 方法的代码长度必须小于65536字节,因此这意味着方法的大小不能超过65535字节

3. 为什么会出现这个问题

现在我们知道了方法的大小限制,让我们看一下可能导致如此大的方法的情况:

  • 代码生成器:大多数大型方法都是使用某些代码生成器(例如ANTLR 解析器)的结果
  • 初始化方法:GUI 初始化可以添加许多细节,例如布局、事件侦听器等等,所有这些都在一种方法中
  • JSP 页面:包含类的一个方法中的所有代码
  • 代码检测:在运行时将字节码添加到编译的类中
  • 数组初始化器:初始化非常大的数组的方法,如下所示:
String[][] largeStringArray = new String[][] {
    { "java", "code", "exceeded", "65355", "bytes" },
    { "alpha", "beta", "gamma", "delta", "epsilon" },
    { "one", "two", "three", "four", "five" }, 
    { "uno", "dos", "tres", "cuatro", "cinco" }, 
        
    //More values
};

4. 如何修复错误

正如我们所指出的,错误的根本原因是方法超过了 65535 字节的阈值。因此, 将出错的方法重构为几个较小的方法 将为我们解决问题。

在数组初始化的情况下,我们可以拆分数组或从文件加载。我们还可以使用静态初始化器。即使我们使用代码生成器,我们仍然可以重构代码。对于大型 JSP 文件,我们可以使用 j sp:include 指令并将其分成更小的单元。

上述问题相对容易处理,但是 当我们在代码中添加检测后出现“代码太大”错误时,事情就变得复杂了 。如果我们拥有代码,我们仍然可以重构该方法。但是当我们从第三方库收到此错误时,我们就已经解决了。通过降低检测级别,我们也许能够解决问题。

5. 结论

在本文中,我们讨论了“代码太大”错误的原因和潜在的解决方案。我们可以随时参考JVM 规范的 Code_Attributes 部分来查找有关此约束的更多详细信息。