JAVA-8中堆上的字符串对象数

JAVA-8中堆上的字符串对象数,java,string,java-8,heap-dump,Java,String,Java 8,Heap Dump,从堆栈溢出中,我了解到,如果我们执行以下操作: String s = new String("ABC"); 然后我们有两个对象一个在堆上,它是字符串,另一个在常量池上,它是“ABC” 但是今天我在堆转储中发现堆上有两个对象。我使用了MAT工具,请查看下面的屏幕截图 所以我的查询是,如果堆上有两个对象,一个是Char[],另一个是String类,另一个是常量池,那么这意味着 String s=newstring(“ABC”)将总共创建3个对象。每个JavaString对象都有一个私有最终字符值

从堆栈溢出中,我了解到,如果我们执行以下操作:

String s = new String("ABC");
然后我们有两个
对象
一个在堆上,它是
字符串
,另一个在
常量
池上,它是
“ABC”

但是今天我在堆转储中发现堆上有两个
对象。我使用了MAT工具,请查看下面的屏幕截图

所以我的查询是,如果堆上有两个对象,一个是
Char[]
,另一个是
String
类,另一个是常量池,那么这意味着


String s=newstring(“ABC”)
将总共创建3个对象。

每个Java
String
对象都有一个
私有最终字符值[]
表示
字符串
的不可变内容(参见源代码)


这似乎反映了您在堆分析中看到的情况。

每个Java
字符串
对象都有一个
私有最终字符值[]
表示
字符串
的不可变内容(参见源代码)


这似乎反映了您在堆分析中看到的情况。

它是内部字段的表示
char[]值
关于游泳池什么也没有。
新的字符串构造函数复制了原来的字符串,原来的字符串已经是内部字段的表示形式了
char[]值
关于游泳池什么也没有。
新的字符串构造函数复制了原来的字符串。字符[]
字符串的内部字段(毕竟,它必须将字符存储在某个地方)

当询问“创建了多少对象”时,不计算内部字段

如果询问此操作创建了多少对象:

Map<Integer, Integer> map = new HashMap<>();
Map Map=newhashmap();

共识是“1”。在内部,创建了许多对象(我没有分析它,但我猜会超过20个),但实现选择不是问题的一部分。

字符[]
字符串的内部字段(毕竟,它必须将字符存储在某个地方)

当询问“创建了多少对象”时,不计算内部字段

如果询问此操作创建了多少对象:

Map<Integer, Integer> map = new HashMap<>();
Map Map=newhashmap();

共识是“1”。在内部,创建了许多对象(我没有分析它,但我的猜测可能超过20个),但实现选择并不是问题的一部分。

互联网上关于字符串文本和字符串池的废话似乎屡见不鲜。只是强调一下,heap in是如何定义的:

2.5.3. 堆 Java虚拟机有一个在所有Java虚拟机线程之间共享的堆。堆是运行时数据区域,所有类实例和数组的内存都是从该区域分配的

因此,无论虚拟机如何实现它,所有对象都生活在堆中,这就是术语heap的定义。堆是内存,所有对象实例都是从中分配的,因此,所有对象都是从堆中分配的。在过去,字符串文本的对象和通过
new
创建的对象通常位于不同的内存区域,但所有这些都是堆的一部分

在最近的JVM中,所有
String
实例都是在同一内存区域中创建的,无论是针对文本还是通过
new
创建的实例

在任何一种情况下,用于管理字符串文本和“插入”字符串的字符串池都是对这些字符串的引用表。表本身可能位于堆之外,而对象则不在堆之外

在您的示例中,您有两个
String
实例和一个
char[]
数组,因为
String
s被实现为
char[]
数组的包装器,并且两个字符串共享该数组。但这是一个实现细节。在其他(较旧的)JVM中,当您使用
string(string)
构造函数从一个字符串构造另一个字符串时,该数组被复制。因此,在这些JVM中,您的示例将创建两个
String
实例和两个
char[]
数组实例


更奇妙的是,通过最新的JVM和适当的配置,JVM将识别具有不同数组但内容相同的
String
实例,并将它们更改为共享一个数组以减少内存消耗。此功能称为。关于堆栈溢出,请参阅:。

在互联网上,关于字符串文本和字符串池的废话似乎屡见不鲜。只是强调一下,heap in是如何定义的:

2.5.3. 堆 Java虚拟机有一个在所有Java虚拟机线程之间共享的堆。堆是运行时数据区域,所有类实例和数组的内存都是从该区域分配的

因此,无论虚拟机如何实现它,所有对象都生活在堆中,这就是术语heap的定义。堆是内存,所有对象实例都是从中分配的,因此,所有对象都是从堆中分配的。在过去,字符串文本的对象和通过
new
创建的对象通常位于不同的内存区域,但所有这些都是堆的一部分

在最近的JVM中,所有
String
实例都是在同一内存区域中创建的,无论是针对文本还是通过
new
创建的实例

在任何一种情况下,用于管理字符串文本和“插入”字符串的字符串池都是对这些字符串的引用表。表本身可能位于堆之外,而对象则不在堆之外

在您的示例中,您有两个
String
实例和一个
char[]
数组,因为
String
s被实现为
char[]
数组的包装器,并且两个字符串共享该数组。但这是一个实现细节。在其他(较旧的)JVM中,当您