彻底理解JVM常量池

ops/2025/2/2 12:57:12/

文章目录


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方法者的引用。
在这里插入图片描述



http://www.ppmy.cn/ops/155036.html

相关文章

变量的作用域和生命周期

一、根据变量的作用域不同,可分为 局部变量 和 全局变量 1. 作用域:变量起作用的范围(变量定义之后,在哪里可以访问变量)。 就近原则:当不同作用域里面有两个或者多个同名变量,那么遵循就近原…

【Qt】06-对话框

对话框 前言一、模态和非模态对话框1.1 概念1.2 模态对话框1.2.1 代码QAction类 1.2.2 模态对话框运行分析 1.3 非模态对话框1.3.1 代码局部变量和成员变量setAttribute 类 1.3.2 现象解释 二、标准对话框2.1 提示对话框 QMessageBox2.1.1 现象及解释 2.2 问题对话框2.2.1 现象…

【3】阿里面试题整理

[1]. ES架构,如何进行路由以及选主 路由:在Elasticsearch(ES)中,默认的路由算法是基于文档的_id。具体来说,Elasticsearch会对文档的_id进行哈希计算,然后对分片数量取模,以确定该文…

Flutter常用Widget小部件

小部件Widget是一个类,按照继承方式,分为无状态的StatelessWidget和有状态的StatefulWidget。 这里先创建一个简单的无状态的Text小部件。 Text文本Widget 文件:lib/app/app.dart。 import package:flutter/material.dart;class App exte…

使用 postman 测试思源笔记接口

思源笔记 API 权鉴 官方文档-中文:https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md 权鉴相关介绍截图: 对应的xxx,在软件中查看 如上图:在每次发送 API 请求时,需要在 Header 中添加 以下键值对&a…

python学opencv|读取图像(四十五)增加掩模:使用cv2.bitwise_and()函数实现图像按位与运算

【1】引言 前序已经对使用cv2.bitwise_and()函数实现图像按位与运算进行了反复探究: python学opencv|读取图像(四十三)使用cv2.bitwise_and()函数实现图像按位与运算-CSDN博客 python学opencv|读取图像(四十四)原理…

C语言自定义数据类型详解(一)——结构体类型(上)

什么是自定义数据类型呢?顾名思义,就是我们用户自己定义和设置的类型。 在C语言中,我们的自定义数据类型一共有三种,它们分别是:结构体(struct),枚举(enum),联合(union)。接下来,我…

第四章 WAL 4.1 WAL文件

4.1 WAL文件 WAL文件用于存储WAL日志。本小节主要介绍WAL文件。 1、WAL文件大小 PG使用64位的无符号整型作为日志文件的寻址空间。如下所示: typedef uint64 XLogRecPtr;//日志寻址类型 static void PreallocXlogFiles(XLogRecPtr endptr)//预分配日志文件uint64 offset;…