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。

java long常量池_Java-常量池相关推荐

  1. java常量信用_JAVA常量

    一.常量定义的基本注意事项. 在Java语言中,主要是利用final关键字(在Java类中灵活使用Static关键字)来定义常量.当常量被设定后,一般情况下就不允许再进行更改.如可以利用如下的形式来定 ...

  2. java线程不执行_java线程池,阿里为什么不允许使用Executors?

    带着问题 阿里Java代码规范为什么不允许使用Executors快速创建线程池? 下面的代码输出是什么? ThreadPoolExecutor executor = new ThreadPoolExe ...

  3. java线程池_Java 线程池 8 大拒绝策略,面试必问!

    点击上方 Java后端,选择设为星标 技术博文,及时送达 前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的 ...

  4. java 10个线程_Java线程池创建10个线程

    Q1:在Java并发编程中,如何扩展和优化线程池? 在java中多线程并不陌生,在一定的范围内,多线程数量的增加会明显提升整个系统的吞吐性能,但是线程本身会极大的耗费内存空间,线程的频繁创建和回收也极 ...

  5. java常量声明_java常量的声明使用定义等

    java常量的声明使用定义等.什么是java常量?java常量的命名规则是什么? 使用java常量的优点有哪些? java常量属于变量的特殊形式.在定义常量的时候要注意的问题: 常量要在定义时赋值 常 ...

  6. java io密集型任务_Java线程池讲解——针对IO密集型任务

    sap java开发技术详解&mdash基础 94.01元 (需用券) 去购买 > 针对 IO 密集型的任务,我们可以针对原本的线程池做一些改造,从而可以提高任务的处理效率. 基本 在阿 ...

  7. java开源对象池_JAVA 对象池

    GenericObjectPool利用一个org.apache.commons.collections.CursorableLinkedList对象来保存对象池里的对象.这种对象池的特色是: 可以设定 ...

  8. java callable 线程池_JAVA 线程池之Callable返回结果

    本文介绍如何向线程池提交任务,并获得任务的执行结果.然后模拟 线程池中的线程在执行任务的过程中抛出异常时,该如何处理. 一,执行具体任务的线程类 要想 获得 线程的执行结果,需实现Callable接口 ...

  9. java 队列线程池_Java线程池Executor使用

    原标题:Java线程池Executor使用 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:减少系统对于,外部 服务的响应时间的等待.第 ...

  10. java定义常量数组_java常量定义总结 转载

    一.常量定义的基本注意事项 在Java语言中,主要是利用final关键字(在Java类中灵活使用Static关键字)来进行Java常量定义.当常量被设定后,一般情况下就 不允许再进行更改.在定义常量时 ...

最新文章

  1. 进制转换converse
  2. [WinAPI] API 4 [注册][创建][消息][第一个框架类窗口]
  3. shop++商品搜索出现乱码的解决方法
  4. 静态方法、类方法、属性方法
  5. WPF入门知识(学习)
  6. bzoj千题计划128:bzoj4552: [Tjoi2016Heoi2016]排序
  7. Flutter React编程范式实践
  8. 周期性取count请求是如何在前台setup的 - Tile count
  9. java如何解压rar文件怎么打开,java解压rar文件
  10. mysql sqldump_mysql sqldump 备份
  11. 信息学奥赛C++语言:等级化的成绩
  12. dropzonejs中文翻译手册 DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库....
  13. 面向云数据库,超低延迟文件系统PolarFS诞生了 1
  14. Lc123验证是不是回文序列
  15. JavaScript对象的常用属性及使用
  16. 抛砖引玉——Stagefright漏洞初探
  17. 基频和倍频的概念_小知识:关于倍频程
  18. 百度无线音乐盒刷打印服务器,百度无线音乐盒引关注 让普通音箱秒变Wi-Fi音箱...
  19. Chrome 浏览器安装 ChroPath 插件
  20. 如何判断一个单链表是否有环?

热门文章

  1. 今日要闻:港股收涨0.17%,BTC出现回调,平台币OKB可顺势跟进
  2. python partition函数_Python partition()函数的使用方法
  3. 使用 LJ1-01 夜间灯光图像检测县域经济发展:与 NPP-VIIRS 数据的比较
  4. 【Java学习路线之JavaWeb】Spring Cloud教程(非常详细)
  5. Android通讯录管理(获取联系人、通话记录、短信消息)
  6. 29. 钛极OS之存储
  7. Linux系统中查看Mysql数据库版本号的四种方法(图文完整版)
  8. 策略模式解决多重if-else
  9. 回应张逸老师(一)圈子文化
  10. linux的删除文件命令和强制删除命令