原文链接:https://hllvm-group.iteye.com/group/topic/38367
请问java 的class文件的常量池的Constant Type为什么没有值为2的tag?
是有什么特别的用处吗?
确实,看Java SE 7版的JVM规范,里面对常量池项的tag的定义是:
tag值的范围是[1, 3-12, 15-16, 18]
可以看到中间没有2、13、14、17。
其实这些空缺的号码都曾经存在,但随着研发过程的推进发现它们的设计不够合理,为了避免兼容性问题,直接把这些号码废除掉,然后向后使用更大的号码来放新类型。
在JVM规范的早期版本的草案里是有tag值为2的常量池项的。
参考JVM规范1.0 Beta版(1995-08-21):http://www.vorlesungen.uni-osnabrueck.de/informatik/java/ftp_area/vmspec.pdf.gz
Tag值为2的是CONSTANT_Unicode。它跟CONSTANT_Utf8的关系顾名思义,前者是用Unicode编码,后者是用UTF-8编码(的变种)来存储字符串常量值。当时还不流行把两字节编码叫UTF-16,而就直接叫Unicode。后来发现其实没必要用两个不同的tag来表示几乎一样的东西,就统一到只用UTF-8版了。
Tag值为13、14的两个我忘记是干嘛的了⋯一时也没找到对应的资料。这个回头我要是找到资料了再更新回来。
JavaCard VM(JCVM)的规范里有Tag值为13:
CONSTANT_Package 13
至于17这个是跟JSR 292相关的。可以参考一些老文档看当年的JSR 292设计:
http://cr.openjdk.java.net/~jrose/pres/201106-indy-javadoc-mlvm-old/2010-0722/
Tag为17的CONSTANT_InvokeDynamic后来非正式叫做CONSTANT_InvokeDynamicTrans(或者“CONSTANT_InvokeDynamic/transitional”),主要是为了兼容于一些JDK7早期开发版的代码。
HotSpot VM在JDK7的开发过程中还有过一个 -XX:+AllowTransitionalJSR292 参数专门用来兼容两种版本的JSR 292设计。