String が作成されたときのメモリ割り当てに関する多くの矛盾する記事を読みました。new 演算子はヒープに文字列を作成し、文字列リテラルは文字列プール [ヒープ] に作成するという記事もあれば、new 演算子はヒープにオブジェクトを作成し、文字列プールに別のオブジェクトを作成するという記事もあります。
これを分析するために、String char 配列と String オブジェクトのハッシュコードを出力する以下のプログラムを作成しました。
import java.lang.reflect.Field;
public class StringAnalysis {
private int showInternalCharArrayHashCode(String s)
throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException {
final Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
return value.get(s).hashCode();
}
public void printStringAnalysis(String s) throws SecurityException,
IllegalArgumentException, NoSuchFieldException,
IllegalAccessException {
System.out.println(showInternalCharArrayHashCode(s));
System.out.println(System.identityHashCode(s));
}
public static void main(String args[]) throws SecurityException,
IllegalArgumentException, NoSuchFieldException,
IllegalAccessException, InterruptedException {
StringAnalysis sa = new StringAnalysis();
String s1 = new String("myTestString");
String s2 = new String("myTestString");
String s3 = s1.intern();
String s4 = "myTestString";
System.out.println("Analyse s1");
sa.printStringAnalysis(s1);
System.out.println("Analyse s2");
sa.printStringAnalysis(s2);
System.out.println("Analyse s3");
sa.printStringAnalysis(s3);
System.out.println("Analyse s4");
sa.printStringAnalysis(s4);
}
}
このプログラムは、次の出力を出力します。
Analyse s1
1569228633
778966024
Analyse s2
1569228633
1021653256
Analyse s3
1569228633
1794515827
Analyse s4
1569228633
1794515827
この出力から、文字列がどのように作成されたかに関係なく、文字列が同じ値を持つ場合、それらは同じ文字配列を共有することが非常に明確です。
今私の質問は、この chararray はどこに保存されているのか、ヒープに保存されているのか、それとも permgen に保存されているのかということです。また、ヒープ メモリ アドレスと permgen メモリ アドレスを区別する方法も知りたいです。
permgen に保存すると、限られた貴重な permgen スペースを使い果たしてしまうので、大きな問題があります。char配列がpermgenではなくヒープに格納されている場合、文字列リテラルもヒープスペースを使用していることを意味します[これは私が読んだことがないものです]。