zoukankan      html  css  js  c++  java
  • Java-常量池

    Java-常量池

           常量池是类文件中最复杂的数据结构。对于JVM字节码来说,如果操作数是很常用的数字,比如 0,这些操作数是内嵌到字节码中的。如果是字符串常量和较大的整数等,Class文件则会把这些操作数存储到常量池中,当使用这些操作数时,会根据常量池的索引位置来查找。

           常量池可以比喻为class文件里的资源仓库,它是Class文件结构中与其他项目关联最多的数据,通常也是占用Class文件空间最大的数据项目之一,另外,他还是在Class文件中第一个出现的表类型数据项目。

    常量池的结构:
    struct {
    u2                constant_pool_count;
    cp_info         constant_pool[ constant_pool_count-1 ];
    }

    (1) 常量池大小(cp_info_count): 常量池是Class文件中第一个出现的变长结构。既然是池就有大小,所以在常量池的入口需要放置一项u2(两个字节)类型的数据,代表常量池容量计数值。与Java中语言习惯不同,这容量是从1开始的而不是从0开始的。0属于保留索引,可供特殊情况使用。(Class文件只有常量池的容量计数是从1开始的,对于其他集合类型,包括接口索引集合,字段表集合,方法表集合等的容量计数都与一般习惯相同,是从0开始的)。

    (2)常量池项(cp_info)集合: 最多包含 n-1 个元素。因为long和double类型的常量会占用两个索引位置,如果常量池包含了这两种类型的元素,实际的常量池的元素个数比 n-1 要小。

    Java虚拟机目前一共定义了14中常量项tag类型,如下表:

    类型tag(标志)描述
    CONSTANT_Utf8_info1UTF-8编码的字符串
    CONSTANT_Integer_info3整形字面量
    CONSTANT_Float_info4浮点型字面量
    CONSTANT_Long_info5长整型字面量
    CONSTANT_Double_info6双精度浮点型字面量
    CONSTANT_Class_info7类或接口的符号引用
    CONSTANT_String_info8字符串类型字面量
    CONSTANT_Fieldref_info9字段的符号引用
    CONSTANT_Methodref_info10类中方法的符号引用
    CONSTANT_InterfaceMethodref_info11接口中方法的符号引用
    CONSTANT_NameAndType_info12字段或方法的部分符号引用
    CONSTANT_MethodHandle_info15表示方法句柄
    CONSTANT_MethodType_info16表示方法类型
    CONSTANT_Dynamic_info17表示一个动态计算常量

    1、 boolean,byte,short ,char 和 float 类型

    Java语言规范定义了boolean,byte,short 和 char 类型的变量在常量池中都会被当作 int 来处理。int 和 float 都是用 4 个字节来表示具体的数值常量。

    接下来测试一下:( 此处在 IDEA里面下载插件jclassbil之后,点击View——>Show Bytecode With Jclassbil 可查看 )

    1.1 Boolean

    public class HelloWorld {
        public final boolean bool = true;
    }
    

    在这里插入图片描述

    1.2 Byte

    public class HelloWorld {
        public final byte aByte = Byte.MAX_VALUE;
    }
    

    在这里插入图片描述
    对于short,char, int 和 float 同样可以测试,此处不再赘述。

    2、long 和 double 类型

    long 和 double 类型的常量都用8个字节表示具体的常量数值( 分为 high_bytes 和 low_bytes )。接下来测试一下:

    2.1 long

    public class HelloWorld {
        public final long aLong = Long.MAX_VALUE;
    }
    

    在这里插入图片描述

    2.2 double

    public class HelloWorld {
        public final double aDouble = Double.MAX_VALUE;
    }
    

    在这里插入图片描述
    可见CONSTANT_Long_info 和 CONSTANT_Double_info 都是占用两个常量池位置(例子中的[09] 和 [10])。

    3、CONSTANT_Utf8_info

    (1) 对于传统的ASCII编码字符 ( 0x0001~0x007F ),UTF-8 用一个字节来表示,如下所示。
    0000 0001 ~ 0000 007F --> 0xxxxxxx
    因此英文字母的ASCII编码和UTF-8编码的结果一样。

    (2) 对于0080 ~ 07FF 范围的字符,UTF-8用2个字节来表示,如下图所示。
    0000 0080 ~ 0000 07FF --> 110xxxxx 10xxxxxx
    程序遇到这种字符的时候,会把第一个字节的110和第二个字节的10去掉,再把剩下的bit组成新的两字节数据。

    (3) 对于 0000 0800 ~ 0000 FFFF 范围的字符,UTF-8 用 3 个字节表示,如下所示。
    0000 0800 ~ 0000 FFFF --> 1110xxxx 10xxxxxx 10xxxxxx
    程序遇到这种字符的时候,会把第一个字节的1110,第二个字节和第三字节的10去掉,再把剩下的bit组成新的3字节数据。

    (4) 对于 0001 0000 ~ 0010 FFFF 范围的字符,UTF-8 用4个字节表示,如下所示。
    0001 0000-0010 FFFF --> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    程序遇到这种字符的时候,会把第一个字节的1110以及第二个,第三,第四字节中的10去掉,再把剩下的bit组成新的4字节数据。

    4、CONSTANT_String_info

    CONSTANT_String_info用来表示java.lang.String类型的常量对象。
    CONSTANT_Utf8_info 存储了字符串真正的内容,而CONSTANT_String_info并不包括字符串的内容,仅仅包含一个指向常量池中的CONSTANT_Utf8_info常量类型的索引。

    public class HelloWorld {
        public final String str = "Hello JVM";
    }
    

    在这里插入图片描述
    在这里插入图片描述
    可看到[07]处是CONSTANT_String_info,存储了一个索引,指向[08],[08]处是CONSTANT_Utf8_info, 存储的才是字符串 Hello JVM

  • 相关阅读:
    linux 备份当前文件
    zz Apache 2.2.15 + PHP 5.3.2+ mysql windows环境配置
    zz iframe父子窗口间js方法调用
    批处理命令里获取本机的机器名
    Cache Concurrency Problem False Sharing
    因为添加assembly到GAC引起的Windows Azure Web Role部署失败
    求数组中满足a[i]<a[j]的相距最远的元素
    Dispose模式
    比较汇编指令 LEA 和 MOV
    读写Unicode字符串(UTF8,UTF16…)
  • 原文地址:https://www.cnblogs.com/jiaohuadehulike/p/14294953.html
Copyright © 2011-2022 走看看