彻底理解JVM常量池

文章目录


java 复制代码
	int a = 10;
	String b = "张三";

  字面量指的是由字母,数字构成的字符串,或者数字常量。只有可能出现在赋值语句 = 的右侧。

  符号引用中的符号,指的是

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

  而常量池的概念,可细分为常量池运行时常量池字符串常量池三块。

  常量池存在于字节码文件中(静态,不属于JVM的任何一块) 运行时常量池是C++中的结构体(动态),也就是说,常量池加载到方法区后成为运行时常量池。

  在JDK1.6 字符串常量池是运行时常量池的一部分,都存放于方法区:
  在JDK7及以后的版本,字符串常量池从方法区的运行时常量池,移动到了堆空间中:
  JVM在实例化字符串时,做了一些优化:

  • 为字符串开辟一个字符串常量池,类似于缓存区。
  • 创建字符串常量时,首先查询字符串常量池是否存在该字符串。
  • 存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中。

  字符串常量池,底层是一个table,存放的是k,v结构,k是引用,v是实际的值。返回的是k(引用)。

  假设都是第一次实例化字符串对象:

java 复制代码
	String s = "a";

  会向堆中的字符串常量池存放一个a字符串,然后返回引用指向s:

java 复制代码
	String s = new String("a");

  会向堆中的字符串常量池存放一个a字符串,还会在堆中创建一个字符串对象,并且返回它的引用指向s。也就是说,会创建两个对象。

java 复制代码
	String s1 = new String("a");
	String s2 = s1.intern();
	System.out.println(s1 == s2);

  首先s1会向堆中的字符串常量池存放一个a字符串,还会在堆中创建一个字符串对象,并且返回它的引用指向s1。然后调用s1的intern()方法,会从字符串常量池中取出a字符串的引用,指向s2。最后的输出是false。因为s1指向的是堆中new String出的实例,而s2指向的是堆中字符串常量池中的a的引用。

  intern()方法,优先去字符串常量池找目标,如果能找到就直接返回字符串常量池中字符串的引用,此时的s1.intern指向的是字符串常量池中的a的引用。

  找不到目标,就放一个在字符串常量池中,然后返回调用intern方法者的引用,此时的s1.intern指向的是堆中s1指向的a(s1.intern和s1指向同一个对象)

  再补充一个案例:

java 复制代码
	String s1 = new String("he") + new String("llo");
	String s2 = s1.intern();
	System.out.println(s1 == s2);

  创建了几个对象?输出的结果如何?具体要根据不同的版本进行分析:

  JDK1.6,在执行第一行代码时,内存图如下所示,s1指向堆中hello的引用。这里的hello是从哪来的?+底层实际调用的是append方法,append调用toString最后会new 一个新的字符串对象

  在执行第二行代码时,位于方法区运行时常量池的字符串常量池中,并没有hello的字面量,于是会在字符串常量池中新创建一个hello对象,指向s2。
  s2和s1指向不是同一个实例,所以输出false。


  JDK1.7及以上,在执行第一行代码时,内存图如下所示:
  在执行第二行代码时,位于堆空间的字符串常量池中,并没有hello字面量,会将hello的引用放入字符串常量池中,并且返回调用intern方法者的引用。


相关推荐
小bo波8 小时前
Java Swing 图形用户界面实验 —— 从算术练习到游戏开发的完整实践
java·课程设计·gui·游戏开发·扫雷·swing
咖啡八杯10 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
SamDeepThinking20 小时前
裁掉那个差程序员后,给你看团队里高手的代码:这个习惯,希望你有
java·后端·程序员
朕瞧着你甚好21 小时前
技术雷达 & Java 集成评估报告 — Apache Tika 3.3.1
java·ai编程
MacroZheng1 天前
短短几天,暴涨2.8万Star!又一款编程神器开源!
java·人工智能·后端
SamDeepThinking1 天前
函数式编程:用BiFunction消除多类型分支的代码重复
java·后端·面试
Flittly2 天前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了2 天前
Java 生成二维码解决方案
java·后端
人活一口气2 天前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP2 天前
Vibe Coding -- 完整项目案例实操
java