字符串常量池与intern方法分析

把雷达强度特征融合于 Cartographer的实现流程 :从地图构建到在线定位 摘要:本文提出在激光SLAM中融合强度特征的方法,解决几何匹配在退化环境中的失效问题。详细介绍了两种高反地图生成方式:离线使用assets_writer工具处理优化轨迹,在线实时累积高反点;以及权重网格的构建与预计算金字塔方法。定位阶段通过加权得分公式融合几何和强度信息,采用自适应缩放策略平衡特征依赖。该方案在不显著增加计算负担的前提下,有效提升了对称环境等退化场景的定位稳定性,对利用人工路标的移动机器人具有实用价值。 阅读详情

文章重要参考https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html。

1 深入理解String#intern方法以及在各JDK版本中的差异

1.1 字符串常量池

字符串常量池存在的意义是使字符串在运行时速度更快,更节省内存。主要的使用方法有三种。
(1)直接双引号引用的String对象会直接存储在字符串常量池中;
(2)直接new String对象时,如果常量池不存在对应String对象,会在池中新创建;
(3)通过String#intern()方法,从字符串常量池中查询当前字符串是否存在,如果不存在就会将当前字符串放入常量池中。

1.2 字符串常量池在不同JDK版本中的位置

在JDK7之前运行时常量池包含字符串常量池存放在方法区,此时hotspot虚拟机对方法区的实现为永久代。

在JDK7中字符串常量池由方法区单独移到了堆中,运行时常量池剩下的东西还在方法区,仍是永久代。

在JDK8中,hotspot移除了永久代而采用元空间(Metaspace)代替,此时字符串常量池仍在堆中,运行时常量池还在方法区,但方法区的实现由永久代变为元空间。

1.3 String#intern()

定义:返回字符串对象的规范化表示形式。

public native String intern();

需要注意的是,intern()方法是一个本地方法;方法的返回值类型是字符串,内容与该字符串相同,但一定取自字符串常量池。

字符串常量池,初始时为空,由String类所私有维护。当intern()方法触发,如果池中已经包含与该String对象相等的字符串,则返回池中字符串。相等的判断,通过equals(Object)方法来实现。否则,将字符串添加到池中,并返回。可以确定的是,通过字符串对象的intern()方法返回的字符串必然取自字符串常量池。

jdk1.6和jdk1.7最大的区别是jdk1.6中 intern 方法会把首次遇到的字符串实例复制到字符串常量池中,并返回此引用;但在jdk1.7中,只是会把首次遇到的字符串实例的引用添加到常量池中(没有复制),并返回此引用。

1.4 通过案例理解String#intern()方法

代码示例1

String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);

String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);

打印结果

jdk6:false false
jdk7:false true

在这里插入图片描述

JDK6中常量池位于PermGen区域中,如图PermGen区和Heap区是独立的区域。由引号声明的字符串直接在字符串常量池中生成,存放在PermGen区,而new生成的String对象存放在Heap区。比较Heap区的对象地址和字符串常量池的对象地址必然是不同的。

Jdk6中,由于PermGen区是一个类静态的区域,主要存储一些加载类的信息,常量池,方法片段等内容,默认大小只有4m。大量使用intern方法容易导致内存溢出java.lang.OutOfMemoryError: PermGen space。正是因为PermGen区域太小,JDK7对字符串常量池做了迁移,迁移到了Java Heap区域。JDK8中直接取消了PermGen区,以元空间来替代。

在这里插入图片描述

1.4.1 s和s2字符串的分析

String s = new String(“1”); 语句的运行会创建2个对象,一个是“1”字符串存放在常量池,另一个是Java Heap中的String对象。

接着执行s.intern();语句,s对象会去字符串常量池查找是否存在"1"字符串,"1"已存在。

String s2 = “1”; 执行该语句,生成引用s2指向字符串常量池中的"1"对象。s的引用地址在Java Heap区,s的引用地址在常量池,地址明显不同。

1.4.2 s3和s4字符串的分析

String s3 = new String(“1”) + new String(“1”);如果忽略前面的s和s2字符串,执行该语句会产生4个对象,分别是字符串常量池中的"1"对象、Java Heap中s3指向的对象以及两个中间对象。此时s3引用对象的内容是“11”,但是字符串常量池中只有"1",而没有"11"对象。

接着指向s3.intern();语句,字符串常量池没有"11",s3会将"11"放入到String常量池中。如果是JDK6,此时PermGen区的字符串常量池会新生成一个"11"对象。而在JDK7中常量池不在PermGen区域,不需要再存储一个对象,而是直接存储堆中对象引用,这个引用指向s3引用对象。

最后,执行String s4 = “11”; 此时字符串常量池已经有"11"这个对象了,即指向s3引用对象的一个引用。此时我们可以察觉到s3和s4两个引用都是指向了Java Heap中的同一个对象,因此JDK7运行结果为true。
如下代码,分析如s3和s4情形大同小异。

String str = new StringBuilder("awe").append("coder").toString();
System.out.println(str.intern() == str);

假设对示例1代码做些许改动:将s3.intern()移到后一句。

String s3 = new String("1") + new String("1");
String s4 = "11";
s3.intern();
System.out.println(s3 == s4); 

打印结果

jdk7:false

参考前面案例的分析思路,很容易就可以分析出原因。s3语句同上,生成Java Heap对象和字符串常量池"1"对象。执行String s4 = “11”;语句时,池中会新创建"11"对象。再执行s3.intern(),池中"11"对象已经存在。因此s3和s4引用是不同的。

1.5 String#intern()方法的最佳实践

合适地使用String#intern()方法可以节省大量内存空间。不合理使用也会严重影响性能。
重要参考:https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html

jre9下载 jdk9 (Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】 立即下载

相关推荐

ENSP:小型企业网络拓扑设计

包含的技术:ospf、dhcp中继、ac+ap、vrrp+mstp、acl、浮动路由、静态路由、vlan划分

weixin_45921302的博客 1万+

java常量池方法区_Java方法区和运行时常量池溢出问题分析

运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。在JDK1.6及之前版本...

weixin_39761195的博客 241

技术美术个人笔记(十六)——Houdini到UE的大地形

文章目录关于地形白模制作关于PDG流程 关于地形白模制作 用heightfield noise和笔刷刷出合适的mask做山形叠加: 用remap可快捷反转mask ,用来做平原地区的小型丘陵: 接着用clip切平最低处,用distort制造侵蚀等,对部分地区用笔刷进行微调拓宽峡谷: 用经过sweep打平的曲线以及裁切的各种多面体用heightfield_project投影制作河道和水池,用blur mask并remap的方法拓宽河道 用distort、erode制造合适的弯曲和侵蚀,同理可挖出月牙形

小谁的博客 3178

方法区和运行时常量池溢出

1. 概述运行时常量池是方法区(永久代)的一部分 参数-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制了常量池的大小。 - JDK6及之前的版本中,字符串常量池在永久代中 - 已发布的JDK7的HotSpot中,已经把原本放在永久代中的字符串常量池移出。2. 运行时常量池导致的内存溢出异常String.intern是一个Native方法,作用: -

李平安 1018

FFmpeg实战:5分钟搞定m3u8视频下载与ts文件合并(附完整命令)

本文详细介绍了如何使用FFmpeg快速下载m3u8视频并合并ts文件为mp4格式。通过简洁的命令行操作,读者可以轻松完成视频处理任务,包括环境准备、链接获取、下载合并及性能优化等实用技巧,特别适合需要高效处理流媒体内容的用户。

weixin_30836759的博客 221

微信支付开发之平台给用户转账到零钱的功能

请求消息中应包含商家批次单号、转账名称、appid、转账总金额、转账总笔数、转账openid、收款用户姓名等信息。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。【转账场景ID】 该批次转账使用的转账场景,如不填写则使用商家的默认场景,如无默认场景可为空,可前往“商家转账到零钱-前往功能”中申请。【转账总笔数】 一个转账批次单最多发起一千笔转账。【商家批次单号】 商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一。

程序员weixin_sodomany的博客 3449

由常量池 运行时常量池 String intern方法想到的(四)之深入理解intern

上篇博文由常量池 运行时常量池 String intern方法想到的(三),写到了String的内存模型,这篇博文讨论下String#intern方法的实现。 这篇博文主要参考自:深入解析String#intern。只是用来学习,无意侵犯版权。声明本文的讨论如在不特殊说明的前提下,使用的是JDK1.6,在特殊场合会说明使用的是JDK1.6还是JDK1.8。 JDK1.6java version

程序员 2411

RK3588 hdmiout调试(一)

RK3588 hdmiout调试(一)

目前从事linux驱动开发,多交流多学习吧 5169

第二章:方法区和运行时常量池溢出

由于运行时常量池属于方法区的一部分,因此两个区域放在一块执行。 String.intern()是一个Native方法,它的作用是如果字符串常量池中已经包含了此String对象的字符串,则返回代表池中这个字符串的String对象;否则将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。 可以通过以下代码测试运行时常量池溢出: public class Test...

weixin_34309543的博客 157

Matlab仿真:均匀面阵方向图、均匀线阵方向图、均匀圆阵方向图

其中,阵列方向图是评价阵列性能的重要参数之一。均匀面阵由若干个相同的阵元构成,阵元间等距排列,阵元的方向图形状为一个圆盘。均匀线阵由若干个相同的阵元构成,阵元间等距排列,阵元的方向图形状为一个矩形。本文将采用Matlab进行仿真,分别实现均匀面阵方向图、均匀线阵方向图和均匀圆阵方向图,并对三种阵列进行比较分析。通过以上代码仿真,我们可以对均匀面阵、均匀线阵和均匀圆阵进行方向图的绘制,进一步分析不同阵列在天线性能方面的差异。Matlab仿真:均匀面阵方向图、均匀线阵方向图、均匀圆阵方向图。

2301_79326857的博客 3436

38.XDMA寄存器详解2-H2C、C2H通道寄存器组剖析

目录 1.上节回顾 2. H2C寄存器剖析 2.1 H2C通道标识寄存器(0x00) 2.2 H2C通道控制寄存器(0x04) 2.3 H2C通道状态寄存器(0x40) 2.4 H2C通道完成描述符数量寄存器(0x48) 2.5 H2C通道对齐寄存器(0x4C) 2.6 H2C通道查询模式回写地址寄存器(0x88、0x8C) 2.7 H2C通道中断掩码寄存器(0x90)​ 2.8 H2C通道性能监视控制寄存器(0xC0) 2.9 H2C通道周期计数性能寄存器(0xC4、0xC8) 2

一个早起的程序员 5204

【java进阶之路】(Java基础篇)[扩展]深入解析String.intern()及字符串常量池问题

申明 : 此文仅仅作为个人学习使用 , 如果有人对于String.intern() 十分想要究其原理 , 请参考此文深入解析String#intern - 美团技术团队 8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊。它的主要使用方法有两种: 直接使用双引号声明出来的String对象会直接存储在常量池中。 如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中

我希望许过的愿望一路生花 护送那时的梦抵挡过风沙 549

详细解读经典跨模态对齐技术Q-Former代码

介绍BLIP2的博客层出不穷,介绍Q-Former的博客也不少,但是详细解读Q-Former代码的博客很少。这篇博客希望以代码为基础,讲明白Q-Former的原理和核心思想,并详细解读一些值得注意的细节。希望读者们能从这一经典技术中朝花夕拾,得到启发。

沉迷单车的追风少年 2459

关于Java String类的intern方法与字符串常量池分析

目录 1. String类简述 2. 字符串常量池 3. intern方法与字符串比较 String类简述 String作为Java中一个较为特殊的类,无论在开发过程还是面试时都是一个值得注意的地方。 首先,String类是一个final类,这意味着它不可被继承同时一旦创建了一个String对象不能被修改。关于这点,通过下面这段代码来解释: String str1 = "3"; str1 = "...

Mr_Liuzhongbin的博客 347

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

JavaSE源码分析(三):字符串常量池与String.intern()方法

aaa

Qi_Si_Miao_Xiang的博客 424

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

从字符串到常量池,一文看懂String类

从字符串到常量池,一文看懂String类设计 从一道面试题开始 看到这个标题,你肯定以为我又要讲这道面试题了 // 这行代码创建了几个对象? String s3 = new String("1"); 是的,没错,我确实要从这里开始 这道题就算你没做过也肯定看到,总所周知,它创建了两个对象,一个位于堆上,一个位于常量池中。 这个答案粗看起来是没有任何问题的,但是仔细思考确经不起推敲。 如果你觉得我说的不对的话,那么可以思考下面这两个问题 你说它创建了两个对象,那么这两个对象分别是怎样创建的呢?我们回

做一个认真的程序员 3103

String intern方法1.6与1.7区别,什么时候将字符串放入changli

public class test{ public static void main(String[] args) { String s3 = new String("hello") ; String intern3 = s3.intern(); String s4 = "hello"; System.out.println(s3 == intern3); ...

weixin_41953890的博客 459

【java系列】String,字符串常量池和intern()方法详解

关于java String intern()方法的一些理解和String类型==结果的判断

m0_61809818的博客 586

字符串intern()方法详解

1. intern()方法简介 如果字符串s在字符串常量池中存在对应字面量,则intern()方法返回该字面量的地址;如果不存在,则创建一个对应的字面量,并返回该字面量的地址 2. String对象与字面量的intern()区别 public static void main(String[] args) { String s1 = new String("字符串"); String s2 = "字符串"; System.out.println

zs357的博客 1万+

深入解析 Java 字符串常量池与 `intern` 方法

字符串常量池的作用:字符串常量池通过重用字符串对象来减少内存占用和提高性能。intern方法的使用intern方法将字符串对象放入字符串常量池,如果常量池中已经存在相同内容的字符串,则返回常量池中该字符串的引用;如果不存在,则将当前字符串对象添加到常量池并返回其引用。字符串的创建和比较:使用new关键字创建的字符串对象存储在堆内存中,而字符串字面量直接引用字符串常量池中的字符串。通过intern方法可以实现字符串对象与常量池中字符串的共享。希望通过本文的详细解释和代码示例,你已经对字符串常量池和。

xycxycooo的博客 1623

【Java随手小记】字符串常量池是怎样的?存储的是引用还是对象?

其实很多资料中写过字符串常量池中存储的是引用,但是在很多视频讲解里又经常简化成对象就在字符串常量池里,固然明白这是为了讲解,简化了一些结构,但是也难免使人产生好奇,到底是怎样的一个结构呢?

m0_51214238的博客 636

【jvm】字符串常量池问题

3.如果常量池中已经包含了一个等于此String对象的字符串(使用equals(Object)方法确定),则返回代表池中这个字符串的String对象的引用。9. 19 new #4 : new一个String对象,对象的引用压入操作数栈。4. 7 new #4 :new一个String对象,对象的引用压入操作数栈。3.简化字符串比较:由于字符串常量池中的字符串是唯一的,可以使用==操作符来比较字符串的引用,从而简化比较操作。

王佑辉的博客 979

JavaSE——字符串常量池(StringTable)

一文学会字符串常量池,还有面试题

chenchenchencl的博客 1359

JVM字符串常量池及String的intern方法详解?

执行上面的代码,会发现打印的结果都是true。那么,为什么本来不相等的字符串,调用了intern方法之后便相等了呢?下面我们就来逐步分析这其中的底层实现。

2501_90424980的博客 735

java中String的两种创建方法、字符串常量池

​ 创建1或2个字符串。如果常量池中已存在字符串常量“abc”,则只会在堆空间创建一个字符串常量“abc”。如果常量池中没有字符串常量“abc”,那么它将首先在池中创建,然后在堆空间中创建,因此将创建总共2个字符串对象。**这句代码里创建了几个字符串对象?检查指定字符串在常量池中是否存在?如果存在,则返回地址,如果不存在,则在常量池中创建。

LIJINGPO的博客 616

关于JDK8中的字符串常量池和String.intern()方法理解

JDK8中的字符串常量池以及String.intern()具体做了什么事情,以及和字符串常量池的联系的解析以及原理思考

njitzyd 888

详解JVM常量池、Class常量池、运行时常量池、字符串常量池

https://blog.youkuaiyun.com/qq_45737068/article/details/107149922?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-

yygr的博客 7976
上一篇: 使用SpringBoot和Maven快速搭建RESTful web服务
下一篇: Linux系统配置Git,并推送代码到远程仓库
Awecoder
博客等级 码龄7年 70粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值