4

我正在尝试帮助遇到 ClassFormatError 的客户。错误消息说

bytecode array size > 65535 at offset=66370 

堆栈跟踪指示在尝试调用实用程序类中的静态方法时发生错误。我无法在我自己的系统上重现该错误。

我尝试用谷歌搜索这个问题(search=classformaterror“字节码数组大小”,包括引号)并找到其他软件的错误报告,但没有任何帮助。我也尝试在这里搜索,但找不到涉及此特定错误消息的结果。(也许我只是没能找到它们……)

知道可能导致此问题的原因是什么吗?我不能发布代码或实际的堆栈跟踪,因为它是专有的。

提前感谢您可以给我的任何指示。

4

3 回答 3

4

要进一步详细说明 Jon Skeet 的回应:

类文件格式为每个方法的字节码数组指定了一个 4 字节长度的字段,但实际上某些结构(局部变量表、行号表和异常表)将其限制为 65535。

其中前两个是可选的,如果您在没有调试信息的情况下编译您的类,则不会编译,但第三个是强制性的。当然,如果方法的后半部分没有异常处理,编译器可能不会注意到。或者更糟糕的是,它可能会溢出并编译损坏的 try-catch 块。

无论哪种方式,实用程序类中的一个或多个方法都太大了,即使没有硬编码的长度限制,也可能应该拆分。

更新:当然,在代码验证器的描述中,代码长度明确限制为 65536 字节。但不可避免地会有一些实现更多地将其视为指导方针。:)

于 2012-08-07T17:35:02.913 回答
2

这表明实用程序类方法基本上太大了,需要拆分。不同的编译器会输出不同数量的代码——我猜不同的虚拟机也可能或多或少地严格执行约束。

此外,您可能会发现在没有调试信息的情况下编译实用程序类会使该方法低于限制 - 但最好将其拆分。

于 2012-08-07T17:22:43.413 回答
1

我想分享 Java VM 规范中的以下内容 - Java SE 7 Edition(准确地说是第 4.7.3 段):

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

所以这似乎是编译器特定的功能。必须说生成如此巨大的代码块在 Java 中应该不是问题(考虑到合理的设计),但在使用自动生成的代码时可能会成为问题。

于 2013-09-10T22:18:22.490 回答