JVM 补充——StringTable

具体哪些String是相等的,各种String的情况,看这个:

https://javaguide.cn/java/basis/java-basic-questions-02.html#string-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF%E4%B8%8D%E5%8F%AF%E5%8F%98%E7%9A%84

String的基本特性

  • String:字符串,使用一对“”引起来表示
    • 声明方式和基础类型类似:String str = “abc”;
    • 也可以:String str = new String(“hello”);
  • String声明为final的,不可被继承
  • String实现了Serializable接口:表示字符串是支持序列化的
    • 实现了Comparable接口:表示String可以比较大小
  • String 在Java8时,内部使用final char[] value来存储字符串数据。Java9改成了byte[]加编码标记哪种正在使用哪种字符编码,节省了一些空间
    • 原因是设计者们发现String里面大部分是拉丁字符,而拉丁字符只占一个字节,浪费了一半的空间
    • 和String有关的类,比如StringBuilder,StringBuffer都做出了相应的改变
  • String的不可变性
    • 当对字符串重新赋值时,会新建一个字面量,然后把新的字面量的地址赋值给String变量
    • 当对现有的字符串进行连接操作时,也是创建新对象,,,
    • 当调用String的replace方法修改指定字符或字符串时,也是返回一个新对象,,,
  • 字符串常量
    • 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
    • 字符串常量池是不会存储相同内存的字符串的【Java语言规范里要求完全相同的字符串字面量应该包含同样的Unicode字符序列(包含同一份码点序列的常量),并且必须是指向同一个String类实例】
    • 字符串常量池是一个固定大小的HashTable(数组+链表),默认大小长度为1009。如果放进常量池的String非常多,就会造成Hash冲突严重,导致链表会很长,链表长了之后调用String.intern时的性能会大幅下降
    • -XX:StringTableSize 可设置StringTable的长度
    • jdk6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。StringTableSize设置没有要求
    • jdk7中StringTable的长度默认值是60013
    • jdk8中默认值一样,但是设置StringTable的长度时,1009是可设置的最小值

String的内存分配

  • 在Java语言中有8种基本数据类型和一种比较特殊的类型String。这些类型为了使它们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念
  • 常量池就类似一个Java系统级别提供的缓存。8种基本数据类型的常量池都是系统协调的。String的常量池比较特殊。它的主要使用方法有两种
    • 直接使用双引号声明出来的String对象会直接储存在常量池中
      • 比如 String info = “atguigu.com”;
    • 如果不是用双引号声明的String对象,可以使用String提供的intern()方法
  • 变化
    • Java 6及以前,字符串常量池存放在永久代
    • Java 7中Oracle的工程师对字符串池的逻辑做了很大的改变,即将字符串常量池的位置调整到Java堆中
      • 所有的字符串都保存在堆中,和其他普通对象一样,这样可以让你在进行调优应用使仅需要调整堆大小就可以了
      • 字符串常量池原先使用得比较少(因为怕永久代的OOM),现在常量池放进堆里面,就可以重新考虑在Java 7中使用String.intern
    • Java 8元空间,字符串常量仍然在堆中
    • 为什么字符串常量池要移入堆中?
      • 1.因为永久代比较小,字符串一多就容易OOM
      • 2.永久代很少GC,大量的空间被占用,不能及时清理

字符串拼接操作

  • 1.常量与常量的拼接结果在常量池,原理是编译期优化
  • 2.常量池中不会存在相同内容的常量
  • 3.只要其中有一个是变量【注意是变量,加了final就是常量引用,是常量相加,不是变量相��】,则相当于在堆中new String() (新建了一个对象),它的值为拼接的结果。变量的拼接原理是StringBuilder
    • 所以,类,方法,变量等,能用final修饰的尽量用
  • 4.如果拼接的结果调用intern()方法,如果常量池没有和这个拼接结果一样的字符串,常量池就新建个对象,并返回此对象地址。如果有了就直接返回那个字符串的地址
    • 拼接之后不调用 intern()方法 常量池是没有这个对象的
  • 请添加图片描述
  • 请添加图片描述
  • 使用StringBuilder拼接字符串比直接拼接字符串好
    • 1.使用StringBuilder拼接比直接拼接快很多倍。直接拼接,会创建过多的StringBuilder和String对象。而使用StringBuilder拼接,自始至终只产生一个StringBuilder对象
    • 2.直接拼接,创建过多对象,给GC带来压力
    • 改进:如果确定拼接之后的字符串长度不会超过某个最大值,可以用StringBuilder构造器指定大小,防止StringBuilder频繁扩容
      • StringBuilder s = new StringBuilder(high level);

intern()的使用

  • 如果不是用双引号声明的String对象,可以使用String提供的intern方法:intern方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。
    • 比如:String myInfo = new String(“I love atguigu”).intern();
  • 也就是说,如果在任意字符串上调用String.intern方法,其返回结果指向的那个类实例,必须和直接以常量形式出现的字符串实例完全相同。因此,下列表达式的值必定为true:
    • (“a”+“b”+“c”).intern() == “abc”
  • 通俗点讲,Interned String 就是确保字符串在内存中只有一份拷贝,这样可以节约内存空间,加快字符串操作任务的执行速度。注意,这个值会被存放在字符串内部池(String Intern Pool)

请添加图片描述

  • new String(“a”) 会产生几个对象?2个

    • 一个是new 的 String对象
    • 一个是在常量池产生的常量 “a”(前提是常量池之前没有"a")
  • new String(“a”) + new String(“b”)会产生几个对象? 6个

    • 一个是StringBuilder因为是变量和变量相加,不是常量+常量
    • 一个是 new 的String
    • 一个是在常量池产生的常量"a"
    • 一个是new 的String
    • 一个是在常量池产生的常量"b"
    • 还有一个!StringBuilder最后还会调用toString()方法,toString方法会new 一个String()对象。
      • 但是!!!在字节码文件看toString的指令,里面没有在常量池创建常量,就是这里的代码,常量池不会多一个"ab"
  • 一个很难的面试题

    • Java7中,将常量池放入了堆中。为了节省空间,它在常量池里不是新建一个常量"11",而是新建一个指针 指向"11",所以s3和s4一样
      • 而在其他情况下,一般都是直接赋值 “”比如 String s = “11”,或者 String s = new String(“11”) 这两个过程都是会在常量池里生成常量的
      • String s3 = new String(“1”) +new String(“1”) 这种生成了String对象,但是没有在常量池里生成常量的情况,真的很特殊
      • **也只有在这种情况下使用 s3.intern()方法会使用 现有String的对象,而不是自己创建一个【其他情况调用****intern()**还是会直接新建常量的】
    • 请添加图片描述
    • 拓展
    • 请添加图片描述
    • 总结String的intern()方法的使用:
      • jdk1.6中,将这个字符串对象尝试放入常量池
        • 如果常量池有,则不会放入。返回已有的常量池中的对象的地址
        • 如果没有,就会将此对象复制一份(就是新建一个值一样的对象),放入常量池,并返回常量池中的对象地址
      • jdk1.7中,将这个字符串对象尝试放入常量池
        • 如果常量池有,则不会放入。返回已有的常量池中的对象的地址
        • 如果没有,则会把对象的引用地址复制一份,放入常量池,并返回常量池中的引用地址
    • 当有大量字符串循环赋值的时候,使用intern()可以大大节省空间和加快速度
      • 请添加图片描述
        请添加图片描述
        G1对堆中String对象的去重(常量池都是唯一的,不用去重)
  • 请添加图片描述

  • 请添加图片描述

  • 感觉应该挺好用,不知道为什么不默认开启

  • 请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/715431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】STL简介 | STL六大组件 | string类 | string类对象操作

目录 1. 什么是STL 2. STL的版本 3. STL的六大组件 4. STL的缺陷 5. 引出string类 6. 标准库中的string类 6.1 string类简介 6.2 string类对象的构造 6.3. string类对象的容量 6.4. string类对象的遍历 6.5. string类对象的修改 6.6. string类非成员函数 6.7. vs…

基于CNN-LSTM-Attention的时间序列回归预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1卷积神经网络(CNN)在时间序列中的应用 4.2 长短时记忆网络(LSTM)处理序列依赖关系 4.3 注意力机制(Attention) 5…

MySQL 学习记录 2

原文:https://blog.iyatt.com/?p13818 13 存储引擎 查看一下前面创建的一张表的创建语句,当时并没有显式指定引擎,MySQL 自动指定的 InnoDB,即默认引擎是这个。 创建表的时候要显式指定引擎可以参考这个语句 查看当前 MySQL …

JWT基于Cookie的会话保持,并解决CSRF问题的方案

使用JWT进行浏览器接口请求,在使用Cookie进行会话保持传递Token时,可能会存在 CSRF 漏洞问题,同时也要避免在产生XSS漏洞时泄漏Token问题,如下图在尽可能避免CSRF和保护Token方面设计了方案。 要点解释如下: 将JWT存入…

Snagit 2024:让你的屏幕活动瞬间变得生动有力 mac/win版

Snagit 2024 屏幕录制与截图软件是一款功能强大的工具,专为现代用户设计,以满足他们在工作、学习和娱乐中对屏幕内容捕捉和分享的需求。这款软件结合了屏幕录制和截图功能,为用户提供了一种高效、便捷的方式来捕捉屏幕上的精彩瞬间。 Snagit…

xxl-job--01--简介

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1.xxl-job1. 1 发展历史1.2 XXL-JOB的系统架构1.3 xxl-job与其他框架对比 2. XXL-JOB的使用2.1 准备工作- 配置调度中心XXL-JOB的数据表 2.2 配置执行器1 引入依赖包…

vue cesium加载点与定位到指定位置

vue cesium定位到指定位置 window.viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(point.longDeg, point.latDeg, 6500000), orientation: {heading: 6.2079384332084935, roll: 0.00031509431759868534, pitch: -1.535}, duration: 3})vue cesium加载点 …

为什么HashMap的键值可以为null,而ConcurrentHashMap不行?

写在开头 今天在写《HashMap很美好,但线程不安全怎么办?ConcurrentHashMap告诉你答案!》这篇文章的时候,漏了一个知识点,知道晚上吃饭的时候才凸显想到,关于ConcurrentHashMap在存储Key与Value的时候&…

【Java】面向对象之多态超级详解!!

文章目录 前言一、多态1.1 多态的概念1.2 多态的实现条件1.3 重写1.3.1方法重写的规则1.3.2重写和重载的区别 1.4 向上转型和向下转型1.4.1向上转型1.4.2向下转型 1.5 多态的优缺点1.5.1 使用多态的好处1.5.2 使用多态的缺陷 结语 前言 为了深入了解JAVA的面向对象的特性&…

基于yolov5的电瓶车和自行车检测系统,可进行图像目标检测,也可进行视屏和摄像检测(pytorch框架)【python源码+UI界面+功能源码详解】

功能演示: 基于yolov5的电瓶车和自行车检测系统_哔哩哔哩_bilibili (一)简介 基于yolov5的电瓶车和自行车检测系统是在pytorch框架下实现的,这是一个完整的项目,包括代码,数据集,训练好的模型…

Unity(第二十一部)动画的基础了解(感觉不了解其实也行)

1、动画组件老的是Animations 动画视频Play Automatically 是否自动播放Animate Physics 驱动方式,勾选后是物理驱动Culling Type 剔除方式 默认总是动画化就会一直执行下去,第二个是基于渲染播放(离开镜头后不执行), …

MySQL中json类型的字段

有些很复杂的信息,我们一般会用扩展字段传一个json串,字段一般用text类型存在数据库。mysql5.7以后支持json类型的字段,还可以进行sql查询与修改json内的某个字段的能力。 1.json字段定义 ip_info json DEFAULT NULL COMMENT ip信息, 2.按…

Doris实战——拈花云科的数据中台实践

目录 前言 一、业务背景 二、数据中台1.0—Lambda 三、新架构的设计目标 四、数据中台2.0—Apache Doris 4.1 新架构数据流转 4.2 新架构收益 五、新架构的落地实践 5.1 模型选择 5.1.1 Unique模型 5.1.2 Aggregate模型 5.2 资源管理 5.3 批量建表 5.4 计算实现…

Stable Diffusion 模型分享:Realistic Stock Photo(真实的库存照片)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 条目内容类型大模型基础模型SDXL 1.0来源CIVITAI作者PromptSharingSamaritan文件名称reali…

Vue3_2024_1天【Vue3创建和响应式,对比Vue2】

前言: Vue3对比Vue2版本,它在性能、功能、易用性和可维护性方面都有显著的提升和改进。 性能优化:模板编译器的优化、对Proxy的支持以及使用了更加高效的Virtual DOM算法等。这使得Vue3的打包大小减少了41%,初次渲染提速55%&#…

【MATLAB源码-第153期】基于matlab的OFDM系统插入导频和训练符号两种信道估计方式误码率对比仿真。

操作环境: MATLAB 2022a 1、算法描述 OFDM(Orthogonal Frequency Division Multiplexing,正交频分复用)是一种高效的无线信号传输技术,广泛应用于现代通信系统,如Wi-Fi、LTE和5G。OFDM通过将宽带信道划分…

使用docker方式测试部署django项目(客户催)

需求 1:已有django项目–weidanyewu 2:希望在服务器上测试部署–客户催 3:没完善django的启动 4:使用临时数据库进行演示 5:使用python3.10版本镜像 6:展示端口80 7:后台执行django程序 8&#…

【C语言】熟悉文件顺序读写函数

前言 本篇详细介绍了 文件顺序读写常用函数,快来看看吧~ 欢迎关注个人主页:逸狼 创造不易,可以点点赞吗~ 如有错误,欢迎指出~ 目录 前言 ​编辑 文件顺序读写函数 fgetc函数 示例 fputc函数 逐个字符写入 写入26个字母 文…

手写模拟器,解放双手!效果炸裂的生产工具

手写模拟器是一款基于Handright的仿手写图片生成软件,可以让你的电脑和手机也能写出漂亮的手写字,你只需要输入你想要写的内容,选择你喜欢的字体和背景,就可以生成一张高仿真的手写图片,用于各种场合,比如做…

代码随想录三刷 day11 | 栈与队列之 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

三刷day11 20. 有效的括号1047. 删除字符串中的所有相邻重复项150. 逆波兰表达式求值 20. 有效的括号 题目链接 解题思路: 有三种不匹配的情况: 第一种情况,字符串里左方向的括号多余了 。 第二种情况,括号没有多余,…