JVM-常量池
Posted 小凉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM-常量池相关的知识,希望对你有一定的参考价值。
在.java文件,讲过javac编译后产生的 .class文件中,头4个字节表示的是魔数,接着魔数后面的第5,6个字节存储的是次版本号,第7,8个字节存储的主板本号.那么再接下来的就是表示常量池入口了.
常量池
可以理解为class文件之中的资源仓库,它是class文件结构中与其他项目关联最多的数据类型,也是占用class文件空间最大的数据项目之一,同时它还是class文件中第一个出现表类型的数据项目.由于常量池的数量是不固定的,所以在常量池入口需要放置一项u2(即2个字节)类型的数据,代表常量池容量计数值(constant-pool-count)(从1开始,将0表示不引用任何常量).
常量池中主要存放两大类常量:字面量(Literal)和符号引用(Synbolic Reference).
- 字面量:比较接近于Java语言层面的常量概念,如文本字符串,声明为final的常量值.
- 符号引用:包括如下三类常量:
- 类和接口的全限定名(Fully Qualified Name)
- 字段的名称和描述符(Descriptor)
- 方法的名称和描述符
常量池中每一项常量都是一个表(14种表).
类型 | 标志 | 描述 |
CONSTANT_utf8_info | 1 | UTF-8编码的字符串 |
CONSTANT_Integer_info | 3 | 整形字面量 |
CONSTANT_Float_info | 4 | 浮点型字面量 |
CONSTANT_Long_info | 5 | 长整型字面量 |
CONSTANT_Double_info | 6 | 双精度浮点型字面量 |
CONSTANT_Class_info | 7 | 类或接口的符号引用 |
CONSTANT_String_info | 8 | 字符串类型字面量 |
CONSTANT_Fieldref_info | 9 | 字段的符号引用 |
CONSTANT_Methodref_info | 10 | 类中方法的符号引用 |
CONSTANT_InterfaceMethodref_info | 11 | 接口中方法的符号引用 |
CONSTANT_NameAndType_info | 12 | 字段或方法的符号引用 |
CONSTANT_MothodType_info | 16 | 标志方法类型 |
CONSTANT_MethodHandle_info | 15 | 表示方法句柄 |
CONSTANT_InvokeDynamic_info | 18 | 表示一个动态方法调用点 |
注意:在这14种表有一个共同的特点,就是开始的第一位是一个u1类型的标志位(tag,就是上表中的标志这一列),代表当前这个常量属于哪种常量类型.下面分析实例的时候会用到.
由于class文件中方法,字段等都需要引用CONSTANT_utf8_info类型常量来描述名称,所以CONSTANT_utf8_info类型常量的最大长度也就是Java中方法,字段名的最大长度(Java程序中如果定义了超过64KB英文字符的变量或方法名,将无法编译).
下面我们接着上一篇分析的class文件继续往下走.
这张图中,我们继续分析了接着主版本号接下来的几个字节,首先是常量池入口是0x0013,转化为十进制就是19,那么表示的范围就是1~18,因为0用来表示不引用任何常量池了.那么也就是说0x0013之后有18个常量池.我们看紧接着的一个常量池,十六进制0x0a用十进制表示就是10,通过上表的标志列我们可以直到,10对应的那一行就是CONSTANT_Methodref_info类型的表,是类中方法的符号引用.那么知道了是CONSTANT_Methodref_info表,就可以根据CONSTANT_Methodref_info表的结构继续往下分析,一直到分析完18个常量池.在这里就不一一往下分析了,直接通过javap工具来直接查看,也顺便查看我们分析的对不对.
我们从javap的结果看出,常量池的范围就是1~18,然后第一个常量池就是Method,也即CONSTANT_Methodref_info.
以上是关于JVM-常量池的主要内容,如果未能解决你的问题,请参考以下文章