当前位置:网站首页>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
边栏推荐
- CVPR 2022 best paper candidate | pip: six inertial sensors realize whole body dynamic capture and force estimation
- SQL injection -day15
- 1200.Minimum Absolute Difference
- [leetcode] 450 and 98 (deletion and verification of binary search tree)
- 函数重入、函数重载、函数重写自己理解
- 维护万星开源向量数据库是什么体验
- QT 打开文件 使用 QFileDialog 获取文件名称、内容等
- Mobile measurement and depth link platform - Branch
- MySQL的索引
- 我的勇敢对线之路--详细阐述,浏览器输入URL发生了什么
猜你喜欢
Stored procedures and functions (MySQL)
Appx code signing Guide
浅谈网络安全之文件上传
代码质量管理
[safe office and productivity application] Shanghai daoning provides you with onlyoffice download, trial and tutorial
Function reentry, function overloading and function rewriting are understood by yourself
【mysql】mysql中行排序
SQL injection -day15
qt-线程等01概念
Docker部署Mysql8的实现步骤
随机推荐
21. (article ArcGIS API for JS) ArcGIS API for JS rectangular acquisition (sketchviewmodel)
VHDL实现任意大小矩阵加法运算
密码学系列之:在线证书状态协议OCSP详解
RestClould ETL 社区版六月精选问答
Clock in during winter vacation
My brave way to line -- elaborate on what happens when the browser enters the URL
VHDL implementation of arbitrary size matrix multiplication
接口数据安全保证的10种方式
Under the tide of "going from virtual to real", Baidu AI Cloud is born from real
Huawei and Xiaomi "copy each other"
Sub pixel corner detection opencv cornersubpix
[Dameng database] after backup and recovery, two SQL statements should be executed
Kalman filter-1
如何自定义Latex停止运行的快捷键
U.S. Air Force Research Laboratory, "exploring the vulnerability and robustness of deep learning systems", the latest 85 page technical report in 2022
Ubuntu 20 installation des enregistrements redisjson
What is the experience of maintaining Wanxing open source vector database
Open3D 网格滤波
C task expansion method
MySQL的索引