今天来总结一下String在jvm内存中的一些分配及其一些优化,包括最新的java8 update20才加入的deduplication特性,还有尚未发布的java 9中的compact特性
jvm中对象存在heap中,还有一块叫做String pool 的地方存放指向heap中字符串对象的指针
String s1 = "hello java"; String s2 = "hello java"; System.out.println(s1 == s2); //true 说明s1和s2指向同一块内存地址
下面解释s1和s2的分配过程,
首先String s1 = "hello java"; ,这个是给s1分配字面值,jvm会先判断常量池中有没有引用指向堆中的一个字符串hello java,
如果没有就在堆中分配对象,然后线程堆栈的变量s1指向堆中的String对象,并且在String pool中维护一个引用指向这个String对象,
然后String s2 = "hello java",这个时候重复之前的过程,但是jvm发现常量池中已经有一个引用指向了堆中包含这个字面值的String对象,就直接在线程栈中分配了指向堆的新的引用S2,
结果如图下
接下来看通过构造函数创建String
String s3 = new String("hello java"); System.out.println(s3 == s2); //false 说明s3和s2 不是指向同一块内存地址
s3是用new创建的对象,这个时候会忽略常量池中的引用,而直接在堆中新建一个对象,这种是不推荐的,下面是s3后的内存图
下面无论通过s3还是s1进行intern,返回的引用都是和s1相同,所以如果常量池中如果存在的话,intern返回的是引用和常量池中表记录的引用是一样的
String s4 = s3.intern(); String s5 = s1.intern(); System.out.println(s4 == s1); //true System.out.println(s5 == s1); //true //上面的图没有话,s4,s5指向的String对象和s1,s2一样
java 8 update 20中如果加入-XX:+UseG1GC -XX:+UseStringDeduplication ,jvm将启动一个叫做Deduplication的优化,如果两个String对象中的char数组是一样的,则会回收掉其中一个,使两个对象share同一个char数组,注意必须启动java7新增的G1回收器
Deduplication和String intern不一样,前者是重用的char数组,并不会减少heap中的String对象数目
而后者可以直接重用现有的String对象
有关统计,大型java应用中25%的heap内存由String对象消耗,有近一半的String对象是重复的,也就是通过String的equals是返回true的,G1 garbage collector 会减少这种内存浪费
java9中新增的compcact机制可以让java中的char不要总是消耗2个byte,而是视情况而定,因为大多数情况其实一个char只需要8个bit就可以,也就是一个byte
参考如下:
http://openjdk.java.net/jeps/192
http://openjdk.java.net/jeps/254
后续可以通过分析字节码,利用java profile工具,分析gc log日志等方式更加细节的分析此类内存情况
相关推荐
"深入理解 Java String#intern() 内存模型" Java String#intern() 内存模型是 Java 语言中一个重要的概念,.string#intern() 方法是 Java 字符串常量池中一个重要的组件。字符串常量池是一个固定大小的 HashMap,桶...
在Java编程语言中,`String`类是极其重要的,它提供了许多用于操作字符串的方法,其中之一便是`intern()`。深入理解`String#intern()`方法对于优化内存使用和理解Java的内存模型至关重要。`intern()`方法是一个非常...
### Java String对象的经典问题 #### 一、String 类与对象机制概述 在Java中,`String`类是一个非常重要的类,它提供了丰富的功能用于处理文本数据。`String`类是不可变的(immutable),这意味着一旦一个`String`...
Java虚拟机(JVM)维护了一个字符串常量池,用于存储所有的字面量字符串和通过`new String()`创建的字符串。如果字符串已经存在于池中,`String`构造函数将不会创建新对象,而是返回池中已有的引用。 ### 7. `...
深入了解Java中的String类是至关重要的,因为String在Java编程中占据着极其重要的位置。下面将对给定的信息进行深入分析: ### 1. String 类是 final 的,不可被继承 在Java中,`String` 类被声明为 `final` 类型...
Java String的intern用法解析 Java String的intern方法是Java中一个非常重要的方法,它可以将字符串常量池中的字符串对象返回给我们。今天,我们将深入探究Java String的intern用法解析,了解它的工作原理和应用...
如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。 在Java中,字符串常量池存在于方法区中。方法...
在Java编程语言中,String类型扮演着至关重要的角色。它被广泛用于表示和操作文本,因为它是不可变的,这确保了字符串的安全性和效率。本文将深入探讨Java中的String类,包括其特性、构造方法、常用方法以及与其他...
Java String 中 intern 的深入讲解 Java String 中的 intern 方法是一个非常重要的概念,它可以将字符串对象存储在字符串常量池中,以便重复使用相同的字符串对象,减少内存的占用。下面我们将深入讲解 Java String...
在Java中,如果我们使用字面值方式创建的String对象,它们是常量池中的字符串常量,如果我们使用new关键字创建的String对象,它们是运行时创建的新对象。例如,String s0="kvill";,String s1=new String("kvill");...
在Java编程语言中,`String`类是使用最广泛的类之一,主要用来处理文本字符串。字符串在Java中被视为不可变对象,这意味着一旦创建了一个`String`对象,就不能更改它的值。下面我们将深入探讨`String`类的一些关键...
String类的intern、split方法 String 类的 intern 方法是一个本地方法,定义如下:public native String intern();该方法返回一个字符串对象的内部化引用,由 String 类维护一个初始为空的字符串的对象池,当 ...
在Java编程中,`java.lang.String`类是极为常见的基础数据类型之一,其重要性和应用范围不言而喻。为了更好地理解和使用String类,本文将从几个关键方面入手,探讨如何更加高效、合理地使用String对象。 #### 一、...
String str1 = new String("Hello").intern(); String str2 = "Hello"; System.out.println(str1 == str2); // 输出 true,因为调用intern()后,str1指向了常量池中的"Hello" ``` 在实际开发中,根据需求选择合适的...
Java 中 String.equals 和 == 的比较 Java 中 String.equals...需要注意的是,在 Java 中,String 是一个特殊的类,它可以使用字面量来创建字符串对象,并且可以使用 intern() 方法将字符串对象添加到字符串常量池中。
这些只是Java String使用的基本知识点,实际的PDF文档可能还涵盖了更多高级话题,如字符串的性能分析、线程安全问题以及最新的Java版本更新对String类的影响等。对于Java开发者来说,深入理解字符串操作是至关重要的...
在 Java 中,可以使用两种方式创建 String 对象:一种是使用字面值赋值方式,例如 `String s = "a";`;另一种是使用 new 关键字,例如 `String s = new String("a");`。这两种方式创建的 String 对象有很大的区别。...
可以使用new StringBuilder(String)方法将Java字符串转换为StringBuilder。 24. 如何检查Java字符串是否为空? 可以使用isEmpty()方法检查Java字符串是否为空。 25. 对于以下代码,创建了多少个对象? String s1...
在 Java 中,String 对象可以通过两种方式来创建:一种是使用双引号括起来的字符串字面值,另一种是使用 new 关键字来创建一个新的 String 对象。 在 Java 中,String 对象是 final 的,也就是说它不能被继承。同时...