运行时常量池中的符号引用/String.intern() /ldc指令
运行时常量池,之前放在方法区(永久代)中,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运行时常量池(来自于java虚拟机规范英文版本+本人的翻译和理解)
加载(loading):通过一个特定的名字,找到类或接口的二进制表示,并通过这个二进制表示创建一个类或接口的过程. 链接:是获取类或接口并把它结合到JVM的运行时状态中,以让类或接口可以被执行 初始化 ...
- JVM笔记3-java内存区域之运行时常量池
1.运行时常量池属于线程共享区中的方法区. 2.运行时常量池用于编译期生成的各种自变量,符号引用,这部分内用将在类加载后接入方法区的运行时常量池中存放. 看如下代码所示,如图: public clas ...
- String放入运行时常量池的时机与String.intern()方法解惑
运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念 ...
- Java 运行时常量池
运行时常量池是方法区的一部分.class中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放在方法区的运行时常量池 ...
- JVM详解之:运行时常量池
目录 简介 class文件中的常量池 运行时常量池 静态常量详解 String常量 数字常量 符号引用详解 String Pool字符串常量池 总结 简介 JVM在运行的时候会对class文件进行加载 ...
- 彻底搞清楚class常量池、运行时常量池、字符串常量池
彻底搞清楚class常量池.运行时常量池.字符串常量池 常量池-静态常量池 也叫 class文件常量池,主要存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference ...
- JVM 常量池、运行时常量池、字符串常量池
常量池: 即class文件常量池,是class文件的一部分,用于保存编译时确定的数据. 保存的内容如下图: D:\java\test\out\production\test>javap -ver ...
- 对JVM运行时常量池的一些理解
1.JVM运行时常量池在内存的方法区中(在jdk8中,移除了方法区) 2.JVM运行时常量池中的内容主要是从各个类型的class文件的常量池中获取,对于字符串常量,可以调用intern方法人为添加,而 ...
- 翻译:JVM虚拟机规范1.7中的运行时常量池部分(一)
原文链接: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4 Java Virtual Machine i ...
随机推荐
- Using the G711 standard
Using the G711 standard Marc Sweetgall, 28 Jul 2006 4.74 (27 votes) 1 2 ...
- 时钟中断TIMER_BH(bottom_half)实现分析
017-12-6 16:27:35时钟中断TIMER_BH(bottom_half)实现分析1.3.1001. 时钟0号中断安装 setup_x86_irq(0, &irq0);@arc ...
- android -------- 常用依赖库
// bannercompile 'com.youth.banner:banner:1.4.9' // recyclecompile 'com.android.support:recyclervie ...
- 架构探险笔记12-安全控制框架Shiro
什么是Shiro Shiro是Apache组织下的一款轻量级Java安全框架.Spring Security相对来说比较臃肿. 官网 Shiro提供的服务 1.Authentication(认证) 2 ...
- 创建springboot的聚合工程(二)
前篇已经成功创建了springboot的聚合工程并成功访问,下面就要开始子工程木块之间的调用: springboot项目的特点,一个工程下面的类必须要放在启动类下面的子目录下面,否则,启动的时候会报错 ...
- vue methods computed watch区别
一.methods和computed computed是计算属性,methods是方法. html: <p>Reversed message: "{{ reversedMessa ...
- python-思路整理-虚拟环境
虚拟环境: 如需多个版本的django或其他框架开发代码时,就可以用虚拟环境 pip3 install virtualenv # 创建虚拟环境 virtualenv virtualenv env1 # ...
- python-day76--django-中间件
什么是中间件?中间件应用场景?和装饰器区别? 中间件 对于所有批量的请求用中间件合适,而对于某些请求个数少用装饰器合适 - 中间件是什么? - 是一个类 - 方法名必须是process_request ...
- 使用ajax请求接口,跨域后cookie无法设置,全局配置ajax;及使用axios跨域后cookie无法设置,全局配置axios
问题一: 使用ajax/axios跨域请求接口,后端放行了,能够正常获取数据,但是cookie设置不进去,后端登录session判断失效 ajax解决办法: //设置ajax属性 crossDomai ...
- [luogu P2319] [HNOI2006]超级英雄
[luogu P2319] [HNOI2006]超级英雄 题目描述 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金. ...