String在内存中如何分布
一、设计思想及原理
设计思想
1、字符串分配和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能。
2、JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。
为字符串开辟一个字符串常量池,类似于缓存区。
创建字符串常量时,首先查询字符串常量池是否存在该字符串。
存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中。
设计原理
底层是hotspot的C++实现,类似一个 HashTable, 保存的本质上是字符串对象的引用。
二、三种字符串创建
Jdk1.7 及以上版本
1.直接赋值
String s = "tom"; // 只会在字符串常量池中,s指向常量池中的引用
创建对象时,JVM会先去常量池中通过 equals(key) 方法,判断是否有相同的对象, 有则直接返回该对象在常量池中的引用,没有则会在常量池中创建一个新对象,再返回引用。
2.new String()
String s = new String("tom"); // 字符串常量池和堆中都有这个对象,s指向内存中的对象引用
创建对象时,先检查字符串常量池中是否有字符串,有则直接去堆内存中创建一个字符串对象,没有则先在字符串常量池里创建一个字符串对象,再去内存中创建一个字符串对象,最后将内存中的引用返回。
3.String.intern()方法
String s1 = new String("tom");
String s2 = s1.intern();
System.out.println(s1 == s2); //false
是一个 native 的方法,当调用 intern方法时,如果字符串常量池已经包含一个等于此字符串对象的字符串(用equals(oject)方法确定),则返回常量池中的字符串。否则,将intern返回的引用指向当前字符串 s1(jdk1.6版本需要将 s1 复制到字符串常量池里)。
三、字符串常量池位置
Jdk1.6及之前: 有永久代,运行时常量池在永久代,运行时常量池包含字符串常量池。
Jdk1.7:有永久代,但已经逐步“去永久代”,字符串常量池从永久代里的运行时常量池分离到堆里。
Jdk1.8及之后: 无永久代,运行时常量池在元空间,字符串常量池里依然在堆里。 字符串常量池在堆里
验证 Demo
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 10000000; i++) {
String str = String.valueOf(i).intern();
list.add(str);
}
}
}
配置JVM参数
jdk6:‐Xms6M ‐Xmx6M ‐XX:PermSize=6M ‐XX:MaxPermSize=6M
jdk8:‐Xms6M ‐Xmx6M ‐XX:MetaspaceSize=6M ‐XX:MaxMetaspaceSize=6M
运行结果
jdk7及以上:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
jdk6:Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
——————仅供学习使用
String在内存中如何分布的更多相关文章
- 一个 -100.01 的double 在内存中怎么存储的. 一个中文String 在内存中占多少直接 utf-8 / GBK
一.-100.01 的double 在内存中怎么存储的 double双精度数据类型存储格式IEEE 双精度格式为8字节64位,由三个字段组成:52 位小数 f : 11 位偏置指数 e :以及 1 位 ...
- C#中string在内存中是如何表示的
不知道你是否有过和我一样的疑问,不同编码的字符串是如何存储在运行时的内存中的呢,计算机在操作string类型的对象时,如何知道这个string是什么编码呢?和文本文件那样有类似BOM的东东在strin ...
- String在内存中如何存储(Java)
JDK1.8中JVM把String常量池移入了堆中,同时取消了“永久代”,改用元空间代替(Metaspace)java中对String对象特殊对待,所以在heap区域分成了两块,一块是字符串常量池(S ...
- String 在内存中如何存储的
基本数据类型由于长度固定,且需要空间比较少,所以直接存储在栈中:而对象比较大,所以栈中只存储一个4btye的引用地址(逻辑地址). java中对String对象特殊对待,所以在heap区域分成了两块: ...
- C++程序中不同变量、函数在内存中内存中的分布情况
一.一个C++编译的程序占用的内存分为以下几个部分 1.栈区:由编译器自动分配 存放函数的参数值,局部变量的值等,操作方式类似于数据结构中的栈. 2.堆区:一般由程序员分配释放,若程序员不释放,程序结 ...
- c++ 程序在内存中的分布
从低地址到高地址: 1.代码区[包含常量的]:存放函数体的二进制代码 2.全局变量区[已初始化 + 未初始化]: 全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量在一块区域, 未初始化的 ...
- 二维数组int[3][2]在内存中的分布方式
- 【问】Windows下C++局部变量在内存中的分布问题
原本是为了看看C++对象模型中子对象赋值给一个父对象和父类型指针指向的域时,到底会不会切割,就打开codebloks写了下面的代码,编译器选的是GNU. #define DEBUG(X) std::c ...
- Java数组在内存中是如何存放的
阅读目录 一维数组 二维数组 数组对象及其引用存放在内存中的哪里? Java中有两种类型的数组: 基本数据类型数组: 对象数组: 当一个对象使用关键字“new”创建时,会在堆上分配内存空间,然后返回对 ...
- Delphi接口的底层实现(接口在内存中仍然有其布局,它依附在对象的内存空间中,有汇编解释)——接口的内存结构图,简单清楚,深刻 good
引言 接口是面向对象程序语言中一个很重要的元素,它被描述为一组服务的集合,对于客户端来说,我们关心的只是提供的服务,而不必关心服务是如何实现的:对于服务端的类来说,如果它想实现某种服务,实现与该服务相 ...
随机推荐
- Tomcat之——宕机自动重启和每日定时启动tomcat
在项目后期维护中会遇到这样的情况,tomcat在内存溢出的时候就出现死机的情况和遇到长时间不响应,需要人工手动关闭和重启服务,针对这样的突发情况,希望程序能自动处理问题而不需要人工关于,所以才有了目前 ...
- selinux中Enforcing, Permissive 和Disable这三种模式的区别
1.如果要马上拒绝运行SELinux:[root@localhost ~]# setenforce 0[root@localhost ~]# getenforcePermissive这条命令会把SEL ...
- 容器到底是个啥?(附Docker学习资源汇总)
目录Docker与容器 初识容器与Docker 为什么要使用Docker Docker优势简介Docker核心概念 Docker客户端和服务器 Docker镜像 D ...
- HashMap 在高并发场景下可能出现的性能问题以及如何规避这些问题
JDK1.8 之前 HashMap 底层是 数组和链表, 之后在之前基础上加上红黑树. 相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转 ...
- MYSQL架构介绍
专栏持续更新中- 本专栏针对的是掌握MySQL基本操作后想要对其有深入了解并且有高性能追求的读者. 第一篇文章主要是对MySQL架构的主要概括,让读者脑海中有个对MySQL大体轮廓,很多地方没有展开细 ...
- Windows IntelliJ IDEA 快捷键终极大全
自动代码 常用的有fori/sout/psvm+Tab即可生成循环.System.out.main方法等boilerplate样板代码 . 例如要输入for(User user : users)只需输 ...
- 线上救急-AWS限频
线上救急-AWS限频 问题 在一个天气炎热的下午,我正喝着可口可乐,悠闲地看着Cursor生成代码,忽然各大群聊中出现了加急@全体的消息,当时就心里一咯噔,点开一看,果然,线上服务出问题,多个能源统计 ...
- 定时任务稳定性解决方案-healthchecks监控系统
背景 目前crontab出现问题后无感知,发现问题不及时,几乎是靠业务部门或用户反馈的方式,研发部门再排查的方式,处理问题.发现问题相对滞后,由此可见需要进一步优化crontab的稳定性,降故障通知前 ...
- 多文件,从url地址中下载文件并进行压缩
直接上代码 Controller层 //我这里直接拿实体接收,entity.getFile()是List<对象>,对象里面存储文件相关的内容 @PostMapping("/zip ...
- windows实现每天定时截图
windows实现每天定时截图 一直想要做一个功能来给自己的电脑每天进行一个截图操作,今天终于做好了,下面分享一下设置的过程. 使用工具 任务计划程序(系统自带) snipaste (手动下载) 设置 ...