这是一个我们难以理解的问题。用文字来描述它很棘手,但我希望能理解其要点。
我知道字符串的实际内容包含在内部 char 数组中。在正常情况下,字符串的保留堆大小将包括 40 个字节加上字符数组的大小。这是解释here。调用子字符串时,字符数组保留对原始字符串的引用,因此字符数组的保留大小可能比字符串本身大很多。
然而,当使用 Yourkit 或 MAT 分析内存使用情况时,似乎会发生一些奇怪的事情。引用 char 数组的保留大小的字符串不包括字符数组的保留大小。
一个例子可能如下(半伪代码):
String date = "2011-11-33"; (24 bytes)
date.value = char{1172}; (2360 bytes)
字符串的保留大小定义为 24 字节,不包括字符数组的保留大小。如果由于许多子字符串操作而对字符数组有很多引用,这可能是有意义的。
现在,当此字符串包含在某种类型的集合(例如数组或列表)中时,此数组的保留大小将包括所有字符串的保留大小,包括字符数组的保留大小。
那么我们就有这样的情况:
Array's retained size = 300 bytes
array[0] = String 40 bytes;
array[1] = String 40 bytes;
array[1].value = char[] (220 bytes)
因此,您必须查看每个数组条目以尝试找出保留大小的来源。
同样,这可以解释为数组包含所有包含对同一字符数组的引用的字符串,因此数组的保留大小完全是正确的。
现在我们解决问题。
我在一个单独的对象中保存了对上面讨论的数组的引用以及具有相同字符串的不同数组。在这两个数组中,字符串引用相同的字符数组。这是意料之中的——毕竟我们谈论的是同一个字符串。然而,这个字符数组的保留大小被计算在这个新对象中的两个数组中。换句话说,保留的大小似乎是两倍。如果我删除第一个数组,那么第二个数组仍将保存对字符数组的引用,反之亦然。这会导致混淆,因为似乎 java 持有对同一个字符数组的两个单独的引用。怎么会这样?这是java的内存问题还是仅仅是分析器显示信息的方式?
这个问题让我们在尝试追踪应用程序中的大量内存使用情况时非常头疼。
再次 - 我希望那里的人能够理解并解释这个问题。
谢谢你的帮助