Java字符串文字的字节码超过65535字节



我一直在读取各种文件中的java字节码,以帮助我了解一个项目的.class文件,在该文件中我需要与没有源代码的第三方库集成和糟糕的文档可用。

对于我自己的娱乐,我通过maven存储库运行了apache bcel库,以查看稀有类和方法属性(例如类型注释(以及原因。

我用特定的jar偶然发现了一个问题,该问题不会专门解码常数字段之一-Constant_UTF8_INFO。库是icu4j-2.6.1.jar (com.ibm.icu:icu4j),特别是LocaleElements_zh__PINYIN.class文件。Apache Bcel失败(以及我自己在符合JVMS版本8和9的快速字节式读取器上的尝试(偶然发现了相同的问题,他们误读了此常数,然后读取下一个字节,该字节将其评估为不正确的常数标签(0x3C/60(。

进行快速检查以查看我是否可以在IDE失败中使用该类(无法解析符号(。使用十六进制编辑器调查实际字体模式,表明该偏移量的常数(0x1AC(是utf8常数(TAG = 0x01(,其长度为0x480E。在文件中向前推进该金额确实具有该位置的字节0x3C。在视觉上查看文件,我可以看到所讨论的常数在位置0x149BD结束,这使得字符串0x1480E的实际长度(本质上是位置0x1AC的前三个字节(。当然,根据JVM ClassFile规范,这当然是不可能的,该规范对于UTF8常数的最大长度为0xFFFF或65535。ClassFile很旧 - 版本46或Java 1.2。

我已经对规范进行了仔细研究,并尝试了不同的实现(较少和更严格(尝试解析这个常数,但它不能解析它,或者打破了其他有效的UTF8常数的读数。

我的问题是,我错过了一些东西,还是编译器错误,在这种情况下,第二个问题是首先会发生这种情况 - 编译器往往会相对彻底检查。最后,Java编译器通常如何管理长度超过65535 bytes 的字符串文字?

,因为您说" classfile很旧 - 版本46或java 1.2",因此由于当时的编译器不拒绝代码,因此classfile确实有可能仅仅破坏了classfile超过极限时。

参见JDK-4309152:#编译器默默生成超过VM限制的字节码:

编译器无法正确执行数字或大小的某些限制 各种classfile组件。这导致代码似乎是为了编译 成功,但在验证期间运行时失败。

这些最初报告为单独的错误,现在已关闭 作为重复的。每个错误号都包括在内 下面的项目。

  1. UTF-8编码字符串有64K的限制。(4071592(

据报道,此错误已为1.3.1_10修复,因此适合时间范围。

请注意,引用的错误#4071592是指尝试在1.2.0及更早的情况下编写过大的字符串时抛出UTFDataFormatException,但#4303354报告说,1.3.0中无效的字符串是无效的。因此,如果有问题的类文件是由javac生成的,则必须使用-target 1.2版本1.3.01.3.1_10

自修复以来,编译器的标准行为是如果某个构造超过类文件/JVM限制,则将编译器错误。

最新更新