【jvm】字符串常量池问题
目录
- 一、基本概念
- 1.1 说明
- 1.2 特点
- 二、存放位置
- 2.1 JDK1.6及以前
- 2.2 JDK1.7
- 2.3 JDK1.8及以后
- 三、工作原理
- 3.1 创建字符串常量
- 3.2 使用new关键字创建字符串
- 四、intern()方法
- 4.1 作用
- 五、优点
- 六、字节码分析
- 6.1 示例1
- 6.1.1 代码示例
- 6.1.2 字节码
- 6.1.3 解析
- 6.2 示例2
- 6.2.1 代码示例
- 6.2.2 分析(jdk8)
- 6.3 示例3
- 6.3.1 代码示例
- 6.2.2 分析(jdk8)
一、基本概念
1.1 说明
- 1.JVM字符串常量池是Java虚拟机(JVM)中一个特殊的内存区域。
- 2.JVM字符串常量池用于存储字符串常量。
- 3.提高性能和减少内存开销。
- 4.字符串常量池是JVM用于存储字符串常量的一个内存区域,避免了相同字符串的重复创建,节省内存空间。
1.2 特点
- 1.字符串常量池中的字符串对象是不可变的。
- 2.相同的字符串常量在池中只存储一份,通过引用共享。
二、存放位置
2.1 JDK1.6及以前
- 1.字符串常量池存放在永久代中,永久代是非堆内存的一部分,用于存储类的元数据、常量、静态变量等。
2.2 JDK1.7
- 1.字符串常量池从永久代移动到了Java堆中,而运行时常量池保留在永久代中。
- 2.这一变化为了适应永久代内存限制问题,并提升性能。
2.3 JDK1.8及以后
- 1.永久代被移除,取而代之的是元空间,字符串常量池仍然位于Java堆中。
- 2.运行时常量池被移动到元空间。
三、工作原理
3.1 创建字符串常量
- 1.使用双引号创建字符串时(String a = “123”; ),JVM会首先在字符串常量池中查找是否已存在该字符串。
- 2.如果存在,则直接返回池中该字符串的引用。
- 3.如果不存在,则在常量池中创建该字符串的实例,并返回其引用。
3.2 使用new关键字创建字符串
- 1.使用new关键字创建字符串对象(如String str = new String(“abc”);)时,JVM会在堆内存中创建一个新的字符串对象,而不管字符串常量池中是否已存在相同的字符串。
- 2.如果需要,可以通过调用intern()方法将新创建的字符串对象放入常量池中。
四、intern()方法
4.1 作用
- 1.intern()方法是String类的一个本地方法。
- 2.用于将字符串对象添加到字符串常量池中。
- 3.如果常量池中已经包含了一个等于此String对象的字符串(使用equals(Object)方法确定),则返回代表池中这个字符串的String对象的引用。
- 4.否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。
五、优点
- 1.节省内存:通过共享相同的字符串常量,避免了不必要的重复创建。
- 2.提高性能:减少了对象创建和垃圾回收的开销。
- 3.简化字符串比较:由于字符串常量池中的字符串是唯一的,可以使用==操作符来比较字符串的引用,从而简化比较操作。
六、字节码分析
6.1 示例1
6.1.1 代码示例
@Test
public void test(){String str1 = new String("hello") + new String("world");String str2 = "helloworld";System.out.println(str1 == str2);
}
6.1.2 字节码
0 new #2 <java/lang/StringBuilder>3 dup4 invokespecial #3 <java/lang/StringBuilder.<init> : ()V>7 new #4 <java/lang/String>
10 dup
11 ldc #5 <hello>
13 invokespecial #6 <java/lang/String.<init> : (Ljava/lang/String;)V>
16 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
19 new #4 <java/lang/String>
22 dup
23 ldc #8 <world>
25 invokespecial #6 <java/lang/String.<init> : (Ljava/lang/String;)V>
28 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
31 invokevirtual #9 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
34 astore_1
35 ldc #10 <helloworld>
37 astore_2
38 getstatic #11 <java/lang/System.out : Ljava/io/PrintStream;>
41 aload_1
42 aload_2
43 if_acmpne 50 (+7)
46 iconst_1
47 goto 51 (+4)
50 iconst_0
51 invokevirtual #12 <java/io/PrintStream.println : (Z)V>
54 return
6.1.3 解析
- 1. 0 new #2 <java/lang/StringBuilder>: 调用StringBuilder的new方法
- 2. 3 dup:复制操作数栈栈顶的一个字(通常是对象引用或数据类型值),并将这个字重新压入栈顶。
- 3. 4 invokespecial #3 <java/lang/StringBuilder. : ()V>:执行StringBuilder的初始化方法,会消耗操作数栈顶一个字。
- 4. 7 new #4 <java/lang/String>:new一个String对象,对象的引用压入操作数栈。
- 5. 10 dup:复制操作数栈栈顶的一个字(通常是对象引用或数据类型值),并将这个字重新压入栈顶。
- 6. 11 ldc #5 :加载栈顶的一个字,即hello。
- 7. 13 invokespecial #6 <java/lang/String. : (Ljava/lang/String;)V>:初始化String,消耗一个string对象的引用和复制的字。
- 8. 16 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;> : append操作,将hello追加进来。
- 9. 19 new #4 <java/lang/String> : new一个String对象,对象的引用压入操作数栈。
- 10. 22 dup:复制操作数栈栈顶的一个字(通常是对象引用或数据类型值),并将这个字重新压入栈顶。
- 11. 23 ldc #8 : 加载栈顶的一个字,即world。
- 12. 25 invokespecial #6 <java/lang/String. : (Ljava/lang/String;)V>:初始化String,消耗一个string对象的引用和复制的字。
- 13. 28 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>: append操作,将world追加进来。
- 14. 31 invokevirtual #9 <java/lang/StringBuilder.toString : ()Ljava/lang/String;> :调用StringBuilder的toString方法
- 15. StringBuilder的toString方法中是直接new了一个String对象。
- 16. 而String str2 = “helloworld”;是常量池的引用。
- 17. 因此不是同一个内存地址,所以结果是false。
6.2 示例2
6.2.1 代码示例
@Testpublic void test(){String str1 = new String("hello") + new String("world");str1.intern();String str2 = "helloworld";System.out.println(str1 == str2);}
6.2.2 分析(jdk8)
- 1.str1是直接new了一个对象,执行intern()方法后,将字符串对象添加到字符串常量池中。
- 2.String str2 = “helloworld”;会先在字符串常量池中找是否有,如果有则返回其对象的引用。
- 3.所以结果是true。
6.3 示例3
6.3.1 代码示例
@Testpublic void test(){String str1 = new String("helloworld") ;String str2 = "helloworld";String intern = str1.intern();System.out.println(str1 == str2);System.out.println(str1 == intern);System.out.println(str2 == intern);}
6.2.2 分析(jdk8)
- 1.str1在堆上new了一个string对象。
- 2.str2是将字面量“helloworld”放入字符串常量池中。
- 3.str1调用intern方法,判断字符串常量池中有没有helloworld,发现有,返回了该字符串常量池的引用即str2。
- 4.此时str1不等于str2。str2和intern是相等的。
相关文章:
【jvm】字符串常量池问题
目录 一、基本概念1.1 说明1.2 特点 二、存放位置2.1 JDK1.6及以前2.2 JDK1.72.3 JDK1.8及以后 三、工作原理3.1 创建字符串常量3.2 使用new关键字创建字符串 四、intern()方法4.1 作用 五、优点六、字节码分析6.1 示例16.1.1 代码示例6.1.2 字节码6.1.3 解析 6.2 示例26.2.1 代…...
STM32学习和实践笔记(39):I2C EEPROM实验
1.I2C总线介绍 I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备,是微电子通信控制领域广泛采用的一种总线标准。 它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。I…...
【Js】导出 HTML 为 Word 文档
在 Web 开发中,有时我们希望用户能够将网页上的 HTML 内容保存为 Word 文档,以便更方便地分享和打印。 html样式 word文档 工具准备 1、 html-docx-js - npm html-docx-js是一个 JavaScript 库,用于将 HTML 内容转换为 Word 文档的格式。它…...
c++入门基础篇(上)
目录 前言: 1.c++的第一个程序 2.命名空间 2.1 namespace的定义 2.2 命名空间使用 3.c++输入&输出 4.缺省参数 5.函数重载 前言: 我们在之前学完了c语言的大部分语法知识,是不是意…...
Java实现数据结构——双链表
目录 一、前言 二、实现 2.1 类的创建 三、对链表操作实现 3.1 打印链表 3.2 插入数据 3.2.1 申请新节点 3.2.2 头插 编辑 3.2.3 尾插 3.2.4 链表长度 3.2.5 任意位置插入 3.3 删除数据 3.3.1 头删 3.3.2 尾删 3.3.3 删除指定位置数据 3.3.4 删除指定数据 3…...
Python应用爬虫下载QQ音乐歌曲!
目录: 1.简介怎样实现下载QQ音乐的过程; 2.代码 1.下载QQ音乐的过程 首先我们先来到QQ音乐的官网: https://y.qq.com/,在搜索栏上输入一首歌曲的名称; 如我在上输入最美的期待,按回车来到这个画面 我们首…...
AWS-WAF-Log S3存放,通过Athena查看
1.创建好waf-cdn 并且设置好规则和log存储方式为s3 2. Amazon Athena 服务 使用 (注意s3桶位置相同得区域) https://docs.aws.amazon.com/zh_cn/athena/latest/ug/waf-logs.html#waf-example-count-matched-ip-addresses 官方文档参考,建一个分区查询表…...
无法解析主机:mirrorlist.centos.org Centos 7
从 2024 年 7 月 1 日起,在 CentOS 7 上,请切换到 Vault 存档存储库: vi /etc/yum.repos.d/CentOS-Base.repo 复制/粘贴以下内容并注意您的操作系统版本。如果需要,请更改。此配置中的版本为 7.9.2009: [base] name…...
自动驾驶论文总结
1.预测 1.1光栅化 代表性论文 Motion Prediction of Traffic Actors for Autonomous Driving using Deep Convolutional Networks (Uber)MultiPath (Waymo) 问题 渲染信息丢失感受野有限高计算复杂度 1.2图神经网络 1.2.1 图卷积 LaneGCN (uber 2020) 1.2.2 边卷积 V…...
【uniapp微信小程序】uniapp微信小程序——页面通信
uniapp微信小程序——页面通信 在开发微信小程序过程中,页面之间的通信是一个常见需求。在使用 uniapp 开发微信小程序时,我们可以采用多种方式实现页面之间的数据传递和状态共享。本文将详细介绍几种常见的实现方式,以供开发者参考。 1. 页…...
【笔记】从零开始做一个精灵龙女-画贴图阶段(上)
此文只是我的笔记,不包全看懂,有问题可评论 PS贴图加工 1.打开ps 拖入uv图,新建图层,设置背景色为灰色,改一下图层名字 2.按z缩小一下uv图层,拖入实体uv图片(目的是更好上色,比如…...
线性代数|机器学习-P22逐步最小化一个函数
文章目录 1. 概述2. 泰勒公式3. 雅可比矩阵4. 经典牛顿法4.1 经典牛顿法理论4.2 牛顿迭代法解求方程根4.3 牛顿迭代法解求方程根 Python 5. 梯度下降和经典牛顿法5.1 线搜索方法5.2 经典牛顿法 6. 凸优化问题6.1 约束问题6.1 凸集组合 Mit麻省理工教授视频如下:逐步…...
SpringCloudAlibaba Nacos配置中心与服务发现
目录 1.配置 1.1配置的特点 只读 伴随应用的整个生命周期 多种加载方式 配置需要治理 1.2配置中心 2.Nacos简介 2.1特性 服务发现与服务健康检查 动态配置管理 动态DNS服务 服务和元数据管理 3.服务发现 1.配置 应用程序在启动和运行的时候往往需要读取一些配置信…...
.NET 一款获取内网共享机器的工具
01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失…...
备考美国数学竞赛AMC8和AMC10:吃透1850道真题和知识点(持续)
距离接下来的AMC8、AMC10美国数学竞赛还有几个月的时间,实践证明,做真题,吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一。 通过做真题,可以帮助孩子找到真实竞赛的感觉,而且更加贴近比赛的内容,…...
旅游景区度假村展示型网站如何建设渠道品牌
景区、度假村、境外旅游几乎每天的人流量都非常高,还包括本地附近游等,对景区及度假村等固定高流量场所,品牌和客户赋能都是需要完善的,尤其是信息展示方面,旅游客户了解前往及查看信息等。 通过雨科平台建设景区度假…...
Python酷库之旅-第三方库Pandas(021)
目录 一、用法精讲 52、pandas.from_dummies函数 52-1、语法 52-2、参数 52-3、功能 52-4、返回值 52-5、说明 52-6、用法 52-6-1、数据准备 52-6-2、代码示例 52-6-3、结果输出 53、pandas.factorize函数 53-1、语法 53-2、参数 53-3、功能 53-4、返回值 53-…...
jvm 06 补充 OOM 和具体工具使用
1.OOM 是什么 OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError。看下关于的官方说明: Thrown when the Java Virtual Machine cannot allocate an object because it is out of memor…...
使用机器学习 最近邻算法(Nearest Neighbors)进行点云分析 (scikit-learn Open3D numpy)
使用 NearestNeighbors 进行点云分析 在数据分析和机器学习领域,最近邻算法(Nearest Neighbors)是一种常用的非参数方法。它广泛应用于分类、回归和聚类分析等任务。下面将介绍如何使用 scikit-learn 库中的 NearestNeighbors 类来进行点云数…...
安装jenkins最新版本初始化配置及使用JDK1.8构建项目详细讲解
导读 1.安装1.1.相关网址1.2.准备环境1.3.下载安装 2. 配置jenkins2.1.安装插件2.2.配置全局工具2.3.系统配置 3. 使用3.1.配置job3.2.构建 提示:如果只想看如何使用jdk1.8构建项目,直接看3.1即可。 1.安装 1.1.相关网址 Jenkins官网:https…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
