当前位置:网站首页>Class常量池与运行时常量池
Class常量池与运行时常量池
2022-07-06 21:00:00 【季风泯灭的季节】
class常量池
java文件在编译成class文件后,在class文件中会生成一个常量池,用于存放代码的字面量、符号引用,如static、void、public等等。这个常量池称为class常量池。用javap命令可生成一个可阅读的JVM字节码指令文件:
javap -v ScheduledBlockChainTask.class
红框标出的就是class常量池信息,常量池中主要存放两大类常量:字面量和符号引用。
int a = 1;
int b = 2;
int c = "abcdefg";
int d = "abcdefg
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
- 为字符串开辟一个字符串常量池,类似于缓存区
- 创建字符串常量时,首先查询字符串常量池是否存在该字符串
- 存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中
- Jdk1.6及之前: 有永久代, 运行时常量池在永久代,运行时常量池包含字符串常量池
- Jdk1.7:有永久代,但已经逐步“去永久代”,字符串常量池从永久代里的运行时常量池分离到堆里
- Jdk1.8及之后: 无永久代,运行时常量池在元空间,字符串常量池里依然在堆里
三种字符串操作
- 直接赋值字符串
String s = "lamu"; // s指向常量池中的引用
- new String();
String s1 = new String("zhuge"); // s1指向内存中的对象引用
- intern方法
String s1 = new String("zhuge");
String s2 = s1.intern();
System.out.println(s1 == s2); //false
intern方法返回的是对象在字符串常量池中的引用。在jdk6及以下的版本中,如果字符串常量池中存在该对象,则返回字符串常量池中对象的引用。如果没有,则将该对象添加到字符串常量池中,返回字符串常量池中该对象的引用。在jdk6以上的版本中,如果字符串常量池中存在该对象,则返回字符串常量池中对象的引用。如果没有,则在堆中查看是否存在该对象,如果有,将堆中该对象的引用放入字符串常量池中并返回。
String拼接符“+”底层会做什么
如果在编译阶段,能确定拼接前后对象的值,那么会在编译阶段直接拼接,将最终的值放入字符串常量池。如果在编译阶段不能知道拼接前后对象的值,那么会在运行阶段创建一个拼接了前后字段值的对象在堆和字符串常量池中。
String s1 = new String("he") + new String("llo");
String s2 = s1.intern();
System.out.println(s1 == s2);
// 在 JDK 1.6 下输出是 false,创建了 6 个对象
// 在 JDK 1.7 及以上的版本输出是 true,创建了 5 个对象
// 当然我们这里没有考虑GC,但这些对象确实存在或存在
// 注意:常量池是否有相应的对象取决于字面量,字面量不存在的对象不会出现在常量池
String s0="hello";
String s1="hello";
String s2="he" + "llo";
System.out.println( s0==s1 ); //true
System.out.println( s0==s2 ); //true s2会在编译期被优化成"hello"。
String s0="hello";
String s1=new String("hello");
String s2="he" + new String("llo");
System.out.println( s0==s1 ); // false s0在常量池,s1在堆中
System.out.println( s0==s2 ); // false new String("llo")没法在编译期优化,所以s2最终在堆中生成
System.out.println( s1==s2 ); // false s1和s2都在堆中,但它们是new出来的两个不同对象
String a = "ab";
String bb = "b";
String b = "a" + bb;
System.out.println(a == b); // false 变量bb在编译期不可知,无法优化
String a = "ab";
final String bb = "b";
String b = "a" + bb;
System.out.println(a == b); // true bb用final修饰,编译期可知,b在编译期可被优化成"ab"
String a = "ab";
final String bb = getBB();
String b = "a" + bb;
System.out.println(a == b); // false 方法即使用final修饰,它也要到运行期来生成动态链接执行代码,因此编译期不可知,无法优化
private static String getBB() {
return "b";
}
String str2 = new StringBuilder("计算机").append("技术").toString();
System.out.println(str2 == str2.intern()); //true
// str2等于堆中的对象"计算机技术",因为没有出现字面量"计算机技术",所以常量池不存在这个对象。
// str2.intern()返回的字符串常量池中对堆对象的引用,所以是同一个对象
String str1 = new StringBuilder("ja").append("va").toString();
System.out.println(str1 == str1.intern()); //false
// java是关键字,在JVM初始化的相关类里放进字符串常量池了。
String s1=new String("test");
System.out.println(s1==s1.intern()); //false
// new出来的对象在常量池中已存在,s1.intern()返回的是常量池中的对象。
//5种整形的包装类Byte,Short,Integer,Long,Character的对象,
//在值小于127时可以使用对象池
Integer i1 = 127; //这种调用底层实际是执行的Integer.valueOf(127),里面用到了IntegerCache对象池
Integer i2 = 127;
System.out.println(i1 == i2);//输出true
//值大于127时,不会从对象池中取对象
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);//输出false
//用new关键词新生成对象不会使用对象池
Integer i5 = new Integer(127);
Integer i6 = new Integer(127);
Integer i7 = 127;
System.out.println(i5 == i6);//输出false
System.out.println(i5 == i7);//输出false
//Boolean类也实现了对象池技术
Boolean bool1 = true;
Boolean bool2 = true;
System.out.println(bool1 == bool2);//输出true
//浮点类型的包装类没有实现对象池技术
Double d1 = 1.0;
Double d2 = 1.0;
System.out.println(d1 == d2);//输出false
边栏推荐
- 2022年上半年HIT行业TOP50
- CVPR 2022 best paper candidate | pip: six inertial sensors realize whole body dynamic capture and force estimation
- What is the experience of maintaining Wanxing open source vector database
- About Tolerance Intervals
- 【mysql】mysql中行排序
- [dpdk] dpdk sample source code analysis III: dpdk-l3fwd_ 001
- ubuntu20安装redisjson记录
- 【C语言】 题集 of Ⅸ
- Huawei and Xiaomi "copy each other"
- 枚举通用接口&枚举使用规范
猜你喜欢
维护万星开源向量数据库是什么体验
如何自定义Latex停止运行的快捷键
10 ways of interface data security assurance
我的勇敢对线之路--详细阐述,浏览器输入URL发生了什么
【DPDK】dpdk样例源码解析之三:dpdk-l3fwd_001
HMS core machine learning service creates a new "sound" state of simultaneous interpreting translation, and AI makes international exchanges smoother
Free PHP online decryption tool source code v1.2
Under the tide of "going from virtual to real", Baidu AI Cloud is born from real
太方便了,钉钉上就可完成代码发布审批啦!
2022夏每日一题(一)
随机推荐
19.(arcgis api for js篇)arcgis api for js线采集(SketchViewModel)
Code quality management
Machine learning notes - bird species classification using machine learning
机器学习笔记 - 使用机器学习进行鸟类物种分类
About Confidence Intervals
密码学系列之:在线证书状态协议OCSP详解
Variables, process control and cursors (MySQL)
什么是 BA ?BA怎么样?BA和BI是什么关系?
复杂因子计算优化案例:深度不平衡、买卖压力指标、波动率计算
Depth analysis of compilation constants, classloader classes, and system class loaders
About Tolerance Intervals
Under the tide of "going from virtual to real", Baidu AI Cloud is born from real
编译常量、ClassLoader类、系统类加载器深度探析
Ubuntu20 installation redisjson record
Appx code signing Guide
VHDL实现任意大小矩阵加法运算
API data interface of A-share index component data
Create applet from 0
ubuntu20安裝redisjson記錄
19. (ArcGIS API for JS) ArcGIS API for JS line acquisition (sketchviewmodel)