【JVM】StringTable 字符串常量池

【个人学习】JVM(10):字符串常量池(StringTable)、String的内存分配、字符串拼接、StringTable的垃圾回收 String被声明为final的,不可被继承String实现了Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:表示String可以比较大小String在jdk8及以前内部定义了用于存储字符串数据。JDK9时改为byte[] 阅读详情

目录

一、字符串常量池

二、String的不可变性

三、String的内存分配

四、intern() 方法与 new String()


一、字符串常量池

JVM的字符串常量池(String Constant Pool)是一块位于方法区(Method Area)的内存区域,用于存储字符串常量。字符串常量池是为了提高性能和节省内存而设计的。在Java编程中,字符串是不可变的(immutable),即一旦创建就不能被修改。为了避免重复创建相同的字符串,JVM将字符串常量放入常量池中,并且多个引用可以指向同一个字符串常量。

当代码中出现字符串常量时,JVM首先检查常量池中是否已经存在该字符串。如果存在,则返回常量池中的引用,而不是创建新的字符串对象。这样可以节省内存空间,同时提高字符串的比较效率。

字符串常量池有以下特点:

  1. 字符串常量池中的字符串是唯一的,不会存在重复的字符串。
  2. 字符串常量池是在编译时确定的,即字符串常量在编译阶段被确定并放入常量池中。
  3. 字符串常量池中的字符串一般存储在方法区(Method Area)中。

可以使用String类的intern()方法将一个字符串对象添加到字符串常量池中。如果字符串常量池中已经存在该字符串,则返回常量池中的引用;如果不存在,则将该字符串对象添加到常量池中并返回引用。

使用字符串常量池可以提高字符串的比较效率,并且在一些特定场景下可以节省内存空间。但是需要注意,过度使用字符串常量池可能会导致内存泄漏或者占用过多的内存,因为字符串常量池中的字符串对象是不可回收的。因此,在使用字符串常量池时需要慎重考虑,并根据具体情况进行合理的字符串管理。

二、String的不可变性

String类在Java中是不可变的(immutable)。这意味着一旦创建了String对象,就无法修改其内容。下面是String的不可变性的几个关键点:

  1. 字符串内容不可变:String对象存储了一个字符序列,一旦创建,其中的字符内容不能被修改。如果尝试修改String对象的字符内容,实际上是创建了一个新的String对象。

  2. String对象是线程安全的:由于String的不可变性,多个线程可以同时访问和共享String对象,而无需担心数据的不一致性。这使得String在多线程环境下具有线程安全性。

  3. 字符串常量池:Java中有一个字符串常量池,用于存储字符串常量。当使用字符串字面量创建String对象时,JVM会首先检查字符串常量池中是否已经存在相同内容的字符串。如果存在,则返回常量池中的引用;如果不存在,则创建一个新的String对象并将其添加到常量池中。这样可以避免创建重复的字符串对象,节省内存。

  4. 安全性:由于String的不可变性,可以将String对象用作方法参数,而无需担心在方法内部被修改。

  5. 缓存哈希值:String类的哈希值是在对象创建时计算出来的,并缓存在对象内部。这样可以避免每次调用哈希方法时都重新计算哈希值。

String的不可变性带来了一些优势,例如线程安全、安全性、哈希值缓存等。但也需要注意,频繁的字符串操作可能会导致大量的中间字符串对象的创建,占用较多的内存。在这种情况下,可以使用StringBuilder或StringBuffer类来进行可变字符串的操作,以提高性能。

三、String的内存分配

在JVM中,String对象的内存分配主要涉及两个部分:字符串常量池和堆内存。

  1. 字符串常量池(String Pool):

    • 字符串常量池是在运行时常量池(Runtime Constant Pool)中的一个特殊部分,用于存储字符串常量。
    • 当使用字面量创建String对象时,JVM首先会在字符串常量池中查找是否存在相同内容的字符串。
      • 如果找到了相同内容的字符串,则返回常量池中的引用。
      • 如果没有找到,则会在常量池中新建一个字符串对象并返回引用。
    • 字符串常量池是在方法区(Method Area)中的一部分,它是一个共享的区域,所有线程都可以访问。
  2. 堆内存(Heap Memory):

    • 当使用new关键字创建String对象时,会在堆内存中分配内存空间,并为字符串对象的内容分配存储空间。
    • 这种方式创建的字符串对象不会被放入字符串常量池中,而是独立于常量池。
    • 堆内存中的字符串对象是可变的,可以通过String的一些方法来修改内容。

需要注意的是:

  • 在Java 7及之前的版本中,字符串常量池位于永久代(Permanent Generation),而在Java 8及之后的版本中,字符串常量池被移至堆内存。
  • 在字符串拼接等操作时,如果使用的是字面量(如"abc" + "def"),编译器会在编译阶段就将其优化为一个新的字面量,而不是在运行时进行拼接操作。

总结:字符串常量池是一个特殊的常量池用于存储字符串常量,而堆内存用于存储通过new关键字创建的字符串对象。

四、intern() 方法与 new String()

intern() 方法与 new String() 在Java中都用于创建字符串对象,但它们的行为和作用略有不同。

intern() 方法:

  • intern() 方法是String类提供的一个实例方法,用于在字符串常量池中查找或添加一个与调用对象内容相同的字符串,并返回常量池中的引用。
  • 如果调用intern()方法的String对象在常量池中已经存在,则返回常量池中的引用;如果不存在,则将该字符串添加到常量池中并返回引用。
  • 通常用于节省内存,避免创建重复的字符串对象,并且可以方便地进行字符串内容的比较。

new String()

  • new String() 是使用关键字new显式地创建一个新的String对象。
  • 不同于直接使用字符串字面量或调用intern()方法,使用new String()会在堆内存中创建一个新的字符串对象,即使字符串内容在常量池中已经存在。
  • 这种方式创建的字符串对象是独立于字符串常量池的,即使内容相同,也会在堆内存中创建一个新的对象。

总结:

  • intern() 方法是用于将字符串对象添加到常量池中或获取常量池中已存在的对象的引用。
  • new String() 是显式地创建一个新的字符串对象,不受字符串常量池的影响。

squidpy 教程 1:在 AnnData Squidpy 中导入空间数据 这些是 10x Genomics Visium 的 Space Ranger 输出提供的 keys,因此是第一个被采用的 keys。在这种情况下,我们假设空间坐标与像素具有相同的比例,因此我们将该值设置为 1。为此,我们将使用模拟数据集,并通过示例展示您应该注意的重要细节,以便利用 AnnData-Scanpy-Squidpy 生态系统的全部功能。并不是绝对必要的,但会节省您大量的输入,因为它是 Squidpy Scanpy 的默认值。正如你所看到的,空间坐标被缩小了,图像被“放大”了。 阅读详情

相关推荐

ANSYS Discovery 2023R1 入门:手把手教你玩转几何模型参数化(附历史追踪避坑指南)

本文详细介绍了ANSYS Discovery 2023R1中几何模型参数化建模的全流程,包括基础设置、参数化实战技巧及历史追踪避坑指南。通过Workbench集成智能参数控制,工程师可以高效完成设计迭代,特别适合需要频繁调整几何模型的仿真场景。文章还提供了参数丢失的预防策略工业应用实例,帮助用户快速掌握这一提升设计效率的核心技能。

weixin_33693070的博客 417

JVM字符串常量池StringTable

介绍JVM字符串常量池,即String Table,包括基本特性内存分配等。

m0_62946761的博客 4873

Npgsql.dll 4.0 C#开发

解决:Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now. Received: 10目前只支持验证明文密码验证md5密码。收到10亲测可用

常量池、运行时常量池字符串常量池StringTable)之间的关系StringTable经典面试题详解

首先:要弄清楚常量池、运行时常量池字符串常量池StringTable)三者之间的关系特性: 三者之间的关系: 1、常量池: 俗称静态常量池,又称常量池表(Constant Pool Table),存在于*.class文件中,就是一张表,虚拟机指令根据这张表找到要执行的类名、类方法、参数类型、字面量等信息 常量池: 虚拟机指令: 2、运行时常量池: 类被加载时,其常量池信息会被放入运行时常量池,并把里面的符号地址变为真实地址。 3、StringTable: 运行时常量池的一部分,储存字符串常量,其存

weixin_43882265的博客 2245

JVM-StringTable(三)

一、常量池与串池StringTable关系 public class StringTableStudy { public static void main(String[] args) { String a = "a"; String b = "b"; String ab = "ab"; } } 将上述代码先编译成字节码,再反编译,得到如下虚拟机指令(部分截图): 常量池: 方法内的指令 StringTable也属于方法区上的一块内存,在数据结构上,是一个哈希表,下面介绍一下指令执

weixin_41979002的博客 494

字符串常量池-StringTable

常量池中的字符串仅仅是符号,在第一次用到时,才会变为对象StringTable利用串池的机制,来避免重复创建字符串对象字符串变量的拼接原理是StringBuilder构建字符串常量的拼接原理是编译期优化可以使用intern方法,主动将串池中还没有的字符串对象放入串池。

菜鸟的博客 1056

Java字符串常量池详解(StringTable

通过观察源码可知,String类的value是被private修饰的,类外是拿不到这个值的。 可能很多人以为String类不可变是因为value[] 这个数组被final修饰,但其实并不是这样的,因为value存储的是一个引用,而不是常量。

qq_63218110的博客 5601

常量池StringTable(字符串常量池池)堆内存

常量池StringTable,堆内存

zi2242975806的博客 402

JVM---StringTable字符串常量池

StringTable字符串常量池) String的基本特性 String:字符串,使用一对 " " 引起来表示。 String s1 = "atguigu" ; // 字面量的定义方式 String s2 = new String("hello"); // new 对象的方式 String 被声明为 final 的,不可被继承。 String 实现了 Serializable 接口:表示字符串是支持序列化的;实现了 Comparable 接口:表示 String 可以比较大

qq_33626996的博客 847

JVM 字符串常量池StringTable

它是一个全局唯一的哈希表,专门用来存储实际的字符串对象引用。字符串真正的内容是存在堆中的。使用StringTable 是为了节省空间,无论程序中有多少个"hello"这样的字符串,只有一个引用。但是如果通过动态拼接生成了新的字符串JVM 会实时检查 StringTable,如果没有,就会把新对象的引用动态添加进去。// false原因:这个新生成的"ab"对象存在于堆内存(Heap)中,而不是字符串常量池中。因此,变量ab指向的是堆中的一个新对象。

weixin_52748928的博客 179

JVM字符串常量池 StringTable

本文通过Java代码示例分析了String.intern()方法的行为特点。当使用StringBuilder创建字符串并调用intern()时,如果常量池没有该字符串,会将对象引用存入常量池;若已存在则直接返回引用。示例显示,不同的创建顺序会导致不同的引用比较结果:先intern()后创建字符串字面量时,所有引用都指向同一对象;而先创建字面量再intern()时,新建对象与常量池引用不同。特别地,使用new String("ab")会先在常量池创建"ab"再新建对象,

猫狗鼠鱼的储物间 242

JVM-第11章-字符串常量池StringTable

JVM字符串常量池StringTable) 1. String的基本特性 String:字符串,使用一对 “” 引起来表示 String s1 = "atguigu" ; // 字面量的定义方式 String s2 = new String("hello"); // new对象的方式 String被声明为final的,不可被继承。 String实现了Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:表示String可以比较大小。

How many ten years in the life time? 728

jvm从HotSpot VM源码看字符串常量池StringTableintern()方法

字符串常量池可以简单理解为就是一个hashmap的结构,记录的是字符串序列String对象引用的映射关系为了在不同的Java进程之间共享字符串池,StringTable还有另外一个名为的MapJDK6中,会在永久代创建String对象再放入StringTable,而在JDK7中则直接将堆中的String对象放入StringTable中OpenJDK中包含HotSpot VM的源码,是完全开源的。OpenJDK源代码如果嫌Github下载太慢也可以去Gitee找国内的镜像。...

HD243608836的博客 739

JVM学习笔记:第九章——StringTable字符串常量池

String——字符串,使用""进行基本表示。注意:字面量方式会检查字符串常量池,若存在则直接返回引用;new方式则是强制在堆内存当中开辟新空间(JDK7之后常量池在堆当中),即使内容相同也会生成新对象(除非调用String.intern)String被声明为final类,不可被继承:意味着String不能有子类设计目的:保障不可变性:防止子类修改字符串内部状态,确保字符串内容一旦创建就不可修改安全性:String广泛用于网络参数、数据库连接、类加载器等关键场景,不可继承防止恶意篡改。

Ycy06721的博客 546

String类型的JVM层面原理总结(字符串常量池-StringTable、运行时常量池、intern、JVM的ldc)

String类型的JVM层面原理总结(字符串常量池-StringTable、运行时常量池、intern、JVM的ldc)

weixin_44182586的博客 282

JVM学习-StringTable字符串常量池

StringTable1.StringTable的特性1.1.面试题1.2.常量池与串池的关系1.3.字符串的拼接1.4.编译器优化1.5.intern方法1.5.1.intern方法(1.8)1.5.2.intern方法(1.6)1.6.StringTable的特性总结2.StringTable位置3.StringTable垃圾回收4.StringTable性能调优 1.StringTable的特性 1.1.面试题 先看几道面试题: String s1 = "a"; String s2 = "b";

Java硬件工程师的博客 2580

JVM字符串常量池StringTable在内存中形式分析

JVM中翻译字符串常量池StringTable)为“String类型常量表”更合适,常量表它存储以双引号包住的String对象的地址引用,而不是String对象本身。通过StringTable可以实现相同内容的字符串共享。 在Java 8,StringTable是存放在内存堆中。(注意与Constant Pool的区别)。 以下两类会纳入“字符串常量表StringTable”管理: 已双引号包住形式申明的字符串String对象 String对象intern()方法获得的String对象

zyplanke的专栏 917

JVM字符串常量池StringTable详解

文章目录1. 字符串拼接操作拼接操作与append的效率对比2. intern()的使用new String("ab")会创建几个对象,new String("a")+new String("b")呢关于String.intern()的面试题总结String的intern()的使用练习练习1练习2intern()效率测试3. StrtingTable的垃圾回收4. G1中的String去重操作实现命令行选项 1. 字符串拼接操作 常量与常量的拼接结果在常量池,原理是编译期优化; 常量池中不会存在相同内

ARSCCC的博客 394

JVMStringTable字符串常量池详解

StringTable特性是什么?StringTable在不同JDK版本的位置区别是什么?StringTable能否进行垃圾回收?读完本篇博文,相信你会得到答案。

Sihang_Xie的博客 1032
上一篇: Vue+SpringBoot打造校园二手交易系统
下一篇: Vue+SpringBoot打造学生日常行为评分管理系统
揣晓丹
博客等级 码龄3年 5725粉丝 504原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

揣晓丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值