これは私たちが理解するのに苦労した質問です。テキストで説明するのは難しいですが、要点を理解していただければ幸いです。
文字列の実際の内容が内部char配列で囲まれていることを理解しています。通常、文字列の保持されるヒープサイズには、40バイトと文字配列のサイズが含まれます。これはここで説明されています。サブ文字列を呼び出す場合、文字配列は元の文字列への参照を保持するため、文字配列の保持サイズは文字列自体よりもはるかに大きくなる可能性があります。
ただし、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)
したがって、保持されたサイズがどこから来ているのかを理解するために、各配列エントリを調べる必要があります。
繰り返しますが、これは、配列が同じ文字配列への参照を保持するすべての文字列を保持しているため、配列の保持サイズが完全に正しいことで説明できます。
ここで問題が発生します。
上記で説明した配列への参照と、同じ文字列を持つ別の配列を別のオブジェクトに保持します。両方の配列で、文字列は同じ文字配列を参照しています。これは予想されることです-結局のところ、同じ文字列について話しているのです。ただし、この文字配列の保持サイズは、この新しいオブジェクトの両方の配列でカウントされます。言い換えれば、保持されるサイズは2倍のようです。最初の配列を削除しても、2番目の配列は文字配列への参照を保持します。その逆も同様です。これは、Javaが同じ文字配列への2つの別々の参照を保持しているように見えるという点で混乱を引き起こします。どうすればいいの?これはJavaのメモリの問題ですか、それともプロファイラーが情報を表示する方法ですか?
この問題は、アプリケーションの膨大なメモリ使用量を追跡しようとするときに多くの頭痛の種を引き起こしました。
繰り返しになりますが、誰かが質問を理解して説明できるようになることを願っています。
ご協力いただきありがとうございます