运行时常量池,之前放在方法区(永久代)中,1.8之后被转移到元空间,放到了native memory中。

具体的数据结构是:(看对象的内存布局,句柄访问还是对象头中保存指向类的元数据的指针,这里以对象头markword之后保存指向元数据指针为例)对象有一个指向类元数据的指针,指向的这个数据结构InstanceClass,InstanceKlass有一个指针指向一个constantPool数据结构(运行时常量池),这个数据结构是一个数组,数组里面元素的排列方式和class文件中是一样的(从1号常量到N号常量),只不过值有变化,7-18里面保存的是数字,根据规则拆开指向的是1-6类型的序号,而1-6类型保存的指向symbol结构体的指针,在class文件中,1-6指向的内容是class文件单独的,而在运行时常量池中,指向的symbol结构体是可以共享的,能做到这一点是因为在引用symbol结构体之前,要经过一个hashTable存取(这个和我们从hashmap中get push的原理差不多),这个hashTable叫symbolTable,存放在元空间,而每个symbol的结构体也存放在元空间。

在ldc命令(以类型1的utf-8为例)中,如果ldc后面的两个字节指向的符号引用没有被解析过,指向的必然是symbol结构体在自己的class对应的运行时常量池中的序号,那么需要首先去StringTable(和symbolTable一样的一个hashTable,存放在元空间中,保存着指向堆中的String对象的引用)找和symbol结构体相等的String对象,如果找到,把自己后面两个字节保存这个String对象的引用,然后把这个string对象的引用放入栈顶。如果没找到,从刚才说的symbol结构体中(下面的红色字体)解析出String对象(这里要先创建一个char数组对象,棕色字体),并放到字符串常量池(StringTable)中(粉色字体,intern方法),然后两个字节替换成引用,入栈。

而String.intern()方法是根据一个String对象去StringTable中找,找到了,方法返回里面对象的引用,找不到,放进去,返回引用。所以返回值是不是原String看之前有没有

oop StringTable::intern(Symbol* symbol, TRAPS) {
if (symbol == NULL) return NULL;
ResourceMark rm(THREAD);
int length;
jchar* chars = symbol->as_unicode(length); // 从 Symbol 中解析出字符串字面量
Handle string;
oop result = intern(string, chars, length, CHECK_NULL); // 调用又一个同名方法
return result;
}

字符串拼接,字节码分析可以见这篇文章:https://www.cnblogs.com/Kidezyq/p/8040338.html

运行时常量池中的符号引用/String.intern() /ldc指令的更多相关文章

  1. 类的加载,链接和初始化——1运行时常量池(来自于java虚拟机规范英文版本+本人的翻译和理解)

    加载(loading):通过一个特定的名字,找到类或接口的二进制表示,并通过这个二进制表示创建一个类或接口的过程. 链接:是获取类或接口并把它结合到JVM的运行时状态中,以让类或接口可以被执行 初始化 ...

  2. JVM笔记3-java内存区域之运行时常量池

    1.运行时常量池属于线程共享区中的方法区. 2.运行时常量池用于编译期生成的各种自变量,符号引用,这部分内用将在类加载后接入方法区的运行时常量池中存放. 看如下代码所示,如图: public clas ...

  3. String放入运行时常量池的时机与String.intern()方法解惑

    运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念 ...

  4. Java 运行时常量池

    运行时常量池是方法区的一部分.class中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放在方法区的运行时常量池 ...

  5. JVM详解之:运行时常量池

    目录 简介 class文件中的常量池 运行时常量池 静态常量详解 String常量 数字常量 符号引用详解 String Pool字符串常量池 总结 简介 JVM在运行的时候会对class文件进行加载 ...

  6. 彻底搞清楚class常量池、运行时常量池、字符串常量池

    彻底搞清楚class常量池.运行时常量池.字符串常量池 常量池-静态常量池 也叫 class文件常量池,主要存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference ...

  7. JVM 常量池、运行时常量池、字符串常量池

    常量池: 即class文件常量池,是class文件的一部分,用于保存编译时确定的数据. 保存的内容如下图: D:\java\test\out\production\test>javap -ver ...

  8. 对JVM运行时常量池的一些理解

    1.JVM运行时常量池在内存的方法区中(在jdk8中,移除了方法区) 2.JVM运行时常量池中的内容主要是从各个类型的class文件的常量池中获取,对于字符串常量,可以调用intern方法人为添加,而 ...

  9. 翻译:JVM虚拟机规范1.7中的运行时常量池部分(一)

    原文链接: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4 Java Virtual Machine i ...

随机推荐

  1. codeforces590b//Chip 'n Dale Rescue Rangers//Codeforces Round #327 (Div. 1)

    题意:从一点到另一点,前t秒的风向与t秒后风向不同,问到另一点的最短时间 挺难的,做不出来,又参考了别人的代码.先得到终点指向起点的向量,设T秒钟能到.如果T>t则受风1作用t秒,风2作用T-t ...

  2. ubuntu vi配置

    1.先卸载tiny版本vi 输入命令:sudo apt-get remove vim-common 2.然后再输入命令: sudo apt-get   install vim sudo vim /et ...

  3. redis之数据类型以及使用

    1 redis数据类型 1. string类型: 字符串类型是 Redis 中最为基础的数据存储类型,它在 Redis 中是二进制安全的,也就是byte类型 最大容量是512M.2. hash类型: ...

  4. Hash应用例子

    八.Hash应用例子搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复 ...

  5. URL和URI的不同

    URL是什么?有什么用? URL(统一资源定位符)是Internet上资源的地址,可以定义为引用地址的字符串,用于指示资源的位置以及用于访问它的协议. URL是在网络上定位资源的最普遍使用的方式,它提 ...

  6. tp5消息队列使用

    composer 安装 扩展包 composer require topthink/think-queue 注意版本:默认安装5.1的扩展包 地址: https://packagist.org/pac ...

  7. openssh允许root用户登录

    openssh默认是不允许root用户登录的,未改配置直接以正确的root账号密码登录会提示用户名密码错误之类. 好消息是openssh配置十分清晰,基本所有的服务端配置都在/etc/ssh/sshd ...

  8. 码云git使用三(本地代码合并)

    现在我们已经学会了把“本地代码上传至码云git服务器”和“从码云git服务器下载代码到本地”. 我们现在学习怎么上传代码到服务器注意事项和步骤. 1.我们修改代码后,我们需要先+Add后再Commit ...

  9. swiper添加了自动滚动效果,然后用手指划过页面,发现自动滚动效果不生效了

    我给swiper添加了自动滚动效果,然后用手指划过页面,发现自动滚动效果不生效了,哪里出了问题呢? 添加参数 autoplayDisableOnInteraction : false,

  10. ubuntu下的网速限制软件wondershaper (2011-09-18 00:00:00)转载▼

    上网或下载的时候我们常常希望网速快一点,但有时我们也需要限制网速,在ubuntu系统下,可以使用wondershaper,不仅可以限制下载速度还可以限制上传速度. 安装好之后,需要使用终端取得管理员权 ...