为什么常量池(在Java类文件中)从1(而不是0)索引?常量_池[0]项是为什么保留的?
从JVM规范(“类文件结构”)中可以看出,“常量池表的索引从1到常量池计数-1。”为什么常量池(在Java类文件中)从1(而不是0)索引?常量_池[0]项是为什么保留的?,java,jvm,.class-file,Java,Jvm,.class File,从JVM规范(“类文件结构”)中可以看出,“常量池表的索引从1到常量池计数-1。” 我很好奇他们为什么要跳过[0],这个条目是为什么保留的。没有保留条目。“[I]ndexed from 1”表示常量池中的第一个条目对应于索引1,因此没有任何常量池[0]。相反,存在一个保留索引0,它肯定不是常量池中的有效索引 记录在案的保留索引的使用似乎很少,但至少第4.7.24节指定了一种用法:方法参数的名称由常量池中的索引表示,对于未命名的参数,该索引为0 还请注意,名称常量\u池\u计数具有误导性。规范明确
我很好奇他们为什么要跳过[0],这个条目是为什么保留的。没有保留条目。“[I]ndexed from 1”表示常量池中的第一个条目对应于索引1,因此没有任何常量池[0]。相反,存在一个保留索引0,它肯定不是常量池中的有效索引 记录在案的保留索引的使用似乎很少,但至少第4.7.24节指定了一种用法:方法参数的名称由常量池中的索引表示,对于未命名的参数,该索引为0
还请注意,名称
常量\u池\u计数
具有误导性。规范明确指出,常量池中只有常量池\u计数-1
项(请参阅第4.1节顶部的结构声明,并与其他一些成员进行比较)。他们跳过了索引0,以便在通常引用常量池项的情况下可以使用它,而是想表示“什么都没有”。它是与空指针等效的常量池
索引0最显著的用途是“捕获所有”异常处理程序。异常处理程序可以指向它要处理的异常类的常量池条目,或者只使用索引0捕获所有内容(这相当于捕获java/lang/Throwable
)。实际上,编译器将生成捕获所有异常处理程序,以实现最终
、同步
块以及try with resources的清理部分等
索引0的其他用途包括:
java/lang/Object的超类
- 没有名称的参数的名称
- 非其他类成员的类的外部类(即顶级类、本地类和匿名类)
- 匿名类的内部名称
- 类的封闭方法,这些类不是立即封闭在方法中的
- 没有版本信息的模块的版本信息
- 没有依赖项信息的模块的依赖项
已同步
和最终
。但是,正如您所说,这种“一网打尽”的习惯用法相当于捕捉java/lang/Throwable
,并不需要特殊的编码。现在,它甚至不保存一个字节,因为异常处理程序总是需要一个stackmap来声明堆栈项,如果是“catch all”,它的类型是java/lang/Throwable
,因此异常处理程序可以引用相同的池条目,而不是零。此外,使用0xFFFF
而不是零可以允许LDC
处理更多的池条目,但是,这个决定是在四分之一世纪前做出的…