Jok*_*ker 1 java string heap-dump java-8
从这个堆栈溢出的字符串对象数量,我开始知道如果我们做一些像:
String s = new String("ABC");
Run Code Online (Sandbox Code Playgroud)
然后我们objects在堆上有两个String,一个在constant池上"ABC",
但今天我拿了堆转储,发现堆上有两个objects它自己.我使用MAT工具同样请找到下面的屏幕截图.
所以我的查询是,如果堆上有两个对象,其中一个Char[]用于String类,另一个用于常量池,那么这意味着
String s = new String("ABC") 将总共创建3个对象.
似乎有关于字符串文字和整个互联网上的字符串池的重复废话.只是为了强调,如何定义堆:
2.5.3.堆
Java虚拟机具有在所有Java虚拟机线程之间共享的堆.堆是运行时数据区,从中分配所有类实例和数组的内存.
因此,无论虚拟机如何实现它,所有对象都存在于堆中,因为这就是定义术语堆的方式.堆是内存,所有对象实例都是从中分配的,因此,所有对象都是从堆中分配的.在过去,字符串文字和对象创建的对象通过new用于生活在不同的内存区域,但仍然,所有这些都是堆的一部分.
在最近的JVM中,所有String实例都在同一内存区域中创建,无论是为文字还是为通过创建的实例创建的new.
在任何一种情况下,管理字符串文字和"实习"字符串的字符串池都是对这些字符串的引用表.表本身可能存在于堆外,而对象则不存在.
在您的示例中,您有两个String实例和一个char[]数组,因为Strings实现为char[]数组的包装器,并且两个字符串共享数组.但这是一个实施细节.在其他(较旧的)JVM中,当使用String(String)构造函数从另一个构造一个字符串时,该数组被复制.因此,在这些JVM中,您的示例将创建两个String实例和两个char[]数组实例.
更奇特的是,使用最新的JVM和适当的配置,JVM将识别String具有不同阵列但内容相同的实例,并更改它们以共享阵列以减少内存消耗.此功能称为字符串重复数据删除.在Stack Overflow上,请参阅:Java 8的字符串重复数据删除功能.
Thechar[]是一个内部字段String(毕竟,它必须将字符存储在某处)。
当询问“创建了多少对象”时,内部字段不计算在内。
如果询问由此创建了多少个对象:
Map<Integer, Integer> map = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)
共识是“1”。在内部,创建了许多对象(我没有分析它,但我的猜测会超过 20 个),但实现选择不是问题的一部分。