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,一经查实,立即删除!

相关文章

[算法沉淀记录] 分治法应用 —— 二分搜索(Binary Search)

分治法应用 —— 二分搜索 算法基本思想 二分搜索(Binary Search)是一种在有序数组中查找特定元素的高效算法。它每次将搜索区间减半,从而快速地缩小搜索范围。二分搜索的基本思想是:首先将待查关键字与数组中间位置的关键字比较…

【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…

使用滤镜属性将网页从彩色变黑白

在某些情况下,例如为了表达哀悼或纪念, 许多网站会将页面颜色从彩色调整为黑白灰色。我到网上查找答案,发现有些是通过javascript或jQuery实现的,我试了一下居然无效。 后来找到一个方法,是仅用一行CSS代码就能搞定的&…

基于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 …

【牛客】SQL130 试卷发布当天作答人数和平均分

描述 现有用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间),示例数据如下: iduidnick_nameachievementleveljobregister_time11001牛客1号31007算…

rke方式安装k8s集群

一、新机环境准备 1.1主机名设置 hostnamectl set-hostname XXX1.2 主机名与ip地址解析 vim /etc/hosts 192.168.0.140 rke 192.168.0.147 master1 192.168.0.152 node1 192.168.0.153 node21.3安装docker tar -xf docker-20.10.24.tgz cp ${SHELL_FOLDER}/docker/*…

【java】19:内部类(3)

成员内部类: 1.可以直接访问外部类的所有成员,包含私有的 class Outer01{//外部类 private int n1 10; public String name "张三"; class Innter01{ public void say0(){ System.out.println("Outer01 的n1 " n1 " outer…

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加载点 …

【蛀牙】如何选择牙刷,牙膏和牙杯(含其他日常牙具:牙线,漱口水,冲牙器)

程序员生活指南之 【蛀牙】如何选择牙刷,牙膏和牙杯(含其他日常牙具:牙线,漱口水,冲牙器) 文章目录 一、如何选择牙刷,牙膏和牙杯1、如何选择牙刷2、如何选择牙膏3、如何选择牙杯 二、日常牙具&…

为什么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框架下实现的,这是一个完整的项目,包括代码,数据集,训练好的模型…

协程库项目—日志模块

日志模块程序结构图 sylarLog ├── LogLevel(日志级别封装类) │ ├── 提供“从日志级别枚举值转换到字符串”、“从字符串转换相应的日志级别枚举值”等方法 ├── LogEvent(日志事件类) │ ├── 封装日志事件的属性…

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

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

高性能服务系列【二】CPU和内存

现代计算机的系统架构十分复杂。在服务器中,双路处理器已经十分常见。最近Arm处理器实现双路共384核心,要知道目前Linux内核最高只支持256核,这就有点尴尬。 多路处理器将越来越普遍,对性能的影响和传统架构有不小的差别&#xf…

MySQL中json类型的字段

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