我已经阅读了很多关于创建 String 时内存分配的冲突文章。有些文章说 new 运算符在堆中创建一个字符串,而字符串字面量是在字符串池 [Heap] 中创建的,而有些文章说 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
从这个输出中可以清楚地看出,无论 String 是如何创建的,如果 String 具有相同的值,那么它们共享相同的 char 数组。
现在我的问题是这个 chararray 存储在哪里,是存储在堆中还是存储在 permgen 中?我还想了解如何区分堆内存地址和永久内存地址。
如果它存储在 permgen 中,我有一个大问题,因为它会占用我宝贵的有限 permgen 空间。如果 char 数组没有存储在 permgen 中,而是存储在堆中,那么这是否意味着字符串文字也使用堆空间 [这是我从未读过的东西]。