Java中几种常量池的区分

转载自  Java中几种常量池的区分

在java的内存分配中,经常听到很多关于常量池的描述,我开始看的时候也是看的很模糊,网上五花八门的说法简直太多了,最后查阅各种资料,终于算是差不多理清了,很多网上说法都有问题,笔者尝试着来区分一下这几个概念。

1.全局字符串池(string pool也有叫做string literal pool)

全局字符串池里的内容是在类加载完成,经过验证,准备阶段之后在堆中生成字符串对象实例,然后将该字符串对象实例的引用值存到string pool中(记住:string pool中存的是引用值而不是具体的实例对象,具体的实例对象是在堆中开辟的一块空间存放的。)。 在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个哈希表,里面存的是驻留字符串(也就是我们常说的用双引号括起来的)的引用(而不是驻留字符串实例本身),也就是说在堆中的某些字符串实例被这个StringTable引用之后就等同被赋予了”驻留字符串”的身份。这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享。

2.class文件常量池(class constant pool)

我们都知道,class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 字面量就是我们所说的常量概念,如文本字符串、被声明为final的常量值等。 符号引用是一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可(它与直接引用区分一下,直接引用一般是指向方法区的本地指针,相对偏移量或是一个能间接定位到目标的句柄)。一般包括下面三类常量:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符

常量池的每一项常量都是一个表,一共有如下表所示的11种各不相同的表结构数据,这每个表开始的第一位都是一个字节的标志位(取值1-12),代表当前这个常量属于哪种常量类型。 每种不同类型的常量类型具有不同的结构,具体的结构本文就先不叙述了,本文着重区分这三个常量池的概念(读者若想深入了解每种常量类型的数据结构可以查看《深入理解java虚拟机》第六章的内容)。

3.运行时常量池(runtime constant pool)

当java文件被编译成class文件之后,也就是会生成我上面所说的class常量池,那么运行时常量池又是什么时候产生的呢?

jvm在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。在上面我也说了,class常量池中存的是字面量和符号引用,也就是说他们存的并不是对象的实例,而是对象的符号引用值。而经过解析(resolve)之后,也就是把符号引用替换为直接引用,解析的过程会去查询全局字符串池,也就是我们上面所说的StringTable,以保证运行时常量池所引用的字符串与全局字符串池中所引用的是一致的。

举个实例来说明一下:

1 2 3 4 5 6 7 8
String str1 = "abc"; String str2 = new String("def"); String str3 = "abc"; String str4 = str2.intern(); String str5 = "def"; System.out.println(str1 == str3);//true System.out.println(str2 == str4);//false System.out.println(str4 == str5);//true

上面程序的首先经过编译之后,在该类的class常量池中存放一些符号引用,然后类加载之后,将class常量池中存放的符号引用转存到运行时常量池中,然后经过验证,准备阶段之后,在堆中生成驻留字符串的实例对象(也就是上例中str1所指向的”abc”实例对象),然后将这个对象的引用存到全局String Pool中,也就是StringTable中,最后在解析阶段,要把运行时常量池中的符号引用替换成直接引用,那么就直接查询StringTable,保证StringTable里的引用值与运行时常量池中的引用值一致,大概整个过程就是这样了。

回到上面的那个程序,现在就很容易解释整个程序的内存分配过程了,首先,在堆中会有一个”abc”实例,全局StringTable中存放着”abc”的一个引用值,然后在运行第二句的时候会生成两个实例,一个是”def”的实例对象,并且StringTable中存储一个”def”的引用值,还有一个是new出来的一个”def”的实例对象,与上面那个是不同的实例,当在解析str3的时候查找StringTable,里面有”abc”的全局驻留字符串引用,所以str3的引用地址与之前的那个已存在的相同,str4是在运行的时候调用intern()函数,返回StringTable中”def”的引用值,如果没有就将str2的引用值添加进去,在这里,StringTable中已经有了”def”的引用值了,所以返回上面在new str2的时候添加到StringTable中的 “def”引用值,最后str5在解析的时候就也是指向存在于StringTable中的”def”的引用值,那么这样一分析之后,下面三个打印的值就容易理解了。

总结

  • 1.全局常量池在每个VM中只有一份,存放的是字符串常量的引用值。
  • 2.class常量池是在编译的时候每个class都有的,在编译阶段,存放的是常量的符号引用。
  • 3.运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个class都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。
         

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

perform指标分析_performace 监控统计

浏览器浏览器是多进程的,js是单线程的。进程:程序运行,资源分配。线程:进程中独立执行的流浏览器有哪些进程Browser进程: 浏览器的主进程(负责协调、主控)GPU进程: 最多一个,用于3D绘制等浏览器…

hibernate正向生成数据库表以及配置——Teacher.hbm.xml

<?xml version"1.0" encoding"utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file au…

数据库中modify和change的区别

修改字段 : ALTER TABLE 表名 MODIFY 字段名 列类型[属性] 无法重命名ALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性] 可以重命名

ExceptionLess新玩法 — 记日志

ExceptionLess 之前也有介绍过这个框架&#xff0c;其实网上也有很多的资料&#xff0c;无论是部署还是一些详细的高级玩法都讲的很清楚也很棒&#xff0c;博主也学习了一些他们的博文&#xff0c;因为很多的东西比如本地部署别人已经写了&#xff0c;我再去写也不免俗套。所以…

19年8月 字母哥 番外篇:周边技术生态

番外篇&#xff1a;周边技术生态 如何使用git查看本教程代码 centos7安装docker图文详解 docker安装mongodb(单点)图文详解 如何使用mybatis自动生成的代码

pt939g联通_尝试修改友华PT939G的省份设置,成功!

本帖最后由 笑西风 于 2020-7-4 08:04 编辑个人感觉友华PT939G无线光猫一体机的配置还不错&#xff0c;核心跟新路由三相同&#xff0c;所以总想折腾它。之前找了各类root/1234&#xff0c;user/1234之类的密码&#xff0c;最终通过CSDN大侠的yhtcAdmin /Cm1YHfw登录了光猫。准…

MySQL中有外键时数据表的删除方法

直接删除grade&#xff0c;被引用的数据表时如下 报错 解决方法 先删除student&#xff0c;要引用的数据表 然后删除grade&#xff0c;被引用的数据表 成功

微软全球副总裁给你发了一张Connect 2016专属邀请卡:信仰再充值!Connect 2016技术大会在线直播!

Connect(); 2016在线直播啦&#xff01;11月16日晚 22:45不见不散&#xff01;快来制作专属自己的大会邀请函&#xff01; Connect(); 是微软面向开发者的一场顶级线上技术盛会&#xff0c;意在为广大开发者带来微软最新的开发技术资讯&#xff0c;每年有超过50万资深开发人员及…

MongoDb安装使用

Microsoft Windows [版本 10.0.17763.107] (c) 2018 Microsoft Corporation。保留所有权利。 C:\Users\Administrator>mongon mongon 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 C:\Users\Administrator>mongo mongo 不是内部或外部命令&#x…

Java中的String与常量池

转载自 Java中的String与常量池string是java中的字符串。String类是不可变的,对String类的任何改变,都是返回一个新的String类对象。下面介绍java中的String与常量池。 1. 首先String不属于8种基本数据类型&#xff0c;String是一个对象。 因为对象的默认值是null&#xff0c;…

tp中怎么执行mysql事务_tp中使用事务

是什么事务是为了防止&#xff0c;多个操作&#xff0c;其中有失败&#xff0c;数据有部分被执行成功的时候使用的。比如&#xff0c;银行&#xff0c;用户转账。张三钱扣了&#xff0c;结果李四钱还增加&#xff01;这个时候需要使用事务&#xff0c;确保张三钱扣了&#xff0…

TRUNCATE vs DELETE命令

TRUNCATE vs DELETE命令 作用&#xff1a;用于完全清空表数据 , 但表结构 , 索引 , 约束等不变 ; 语法&#xff1a; TRUNCATE [TABLE] table_name;-- 清空年级表 TRUNCATE grade注意&#xff1a;区别于DELETE命令 相同 : 都能删除数据 , 不删除表结构 , 但TRUNCATE速度更快 …

mysql 时间 1_(转)mysql日期时间函数1

MySQL 日期跟时间函数(一)作者&#xff1a; Mr.ZhangMySQL 日期跟时间的样式在MySQL 中有很多有用处的日期跟时间函数。我们常常看到许多应用于日期的计算是在代码方面上进行的&#xff0c;但是其实他们完全可以使用MySQL中自带的函数来实现。在我们实际的查看MySQL的时间跟日期…

ASP.NET Core 整合Autofac和Castle实现自动AOP拦截

前言&#xff1a; 除了ASP.NETCore自带的IOC容器外&#xff0c;我们还可以使用其他成熟的DI框架&#xff0c;如Autofac&#xff0c;StructureMap等&#xff08;笔者只用过Unity&#xff0c;Ninject和Castle&#xff09;。 1.ASP.NET Core中的Autofac 首先在Project.json的Depen…

hibernate多对多、正向工程创建数据表——访问温馨提示

大家都知道&#xff0c;hibernate可以反向生成实体类以及配置文件&#xff0c;但是正向的可能做的人并不是很多&#xff0c;什么是正向&#xff0c;什么是反向呢&#xff0c;正向指的是先有了实体类&#xff08;entity&#xff09;&#xff0c;然后在根据你的实体类通过hiberna…

SQL---空字符串不等于null

查询没有写家庭住址的同学 SELECT studentname FROM student WHERE Address IS NULL; 空字符串不等于null&#xff0c;所以输入的是空字符串&#xff0c;仍然可以查到 正确做法 SELECT studentname FROM student WHERE Address’’ OR Address IS NULL;

Redis安装与配置( Windows10 )

Redis安装与配置&#xff08; Windows10 &#xff09; 2018-09-22 17:54:21 gcl_air 阅读数 13357更多 分类专栏&#xff1a; redis 版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接…

我为什么选择Angular 2?

没有选择是痛苦的&#xff0c;有太多的选择却更加痛苦。而后者正是目前前端领域的真实写照。新的框架层出不穷&#xff1a;它难吗&#xff1f;它写得快吗&#xff1f;可维护性怎样&#xff1f;运行性能如何&#xff1f;社区如何&#xff1f;前景怎样&#xff1f;好就业吗&#…

java io系列09之 FileDescriptor总结

转载自 java io系列09之 FileDescriptor总结FileDescriptor 介绍 FileDescriptor 是“文件描述符”。FileDescriptor 可以被用来表示开放文件、开放套接字等。以FileDescriptor表示文件来说&#xff1a;当FileDescriptor表示某文件时&#xff0c;我们可以通俗的将FileDescri…