【发布时间】:2013-04-15 15:53:14
【问题描述】:
我已经阅读了很多关于创建 String 时内存分配的冲突文章。 有的文章说 new 操作符在堆中创建一个字符串,而字符串字面量是在字符串池 [Heap] 中创建的,而有些文章说 new 操作符在堆中创建一个对象,在字符串池中创建另一个对象。
为了分析这一点,我编写了以下程序,它打印字符串字符数组和字符串对象的哈希码:
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 中而是存储在堆中,那么这是否意味着字符串文字也使用堆空间 [这是我从未读过的东西]。
【问题讨论】:
-
Java 编译器实在是太聪明了。试试
"...".toCharArray()之类的。但随后信息水平下降到零。 -
this 可能有用
-
如果您从
StringBuilder构建String会更有说服力,也许是通过调用单独的例程来附加部分字符串值。 -
@Anirudh:我读了那个链接,但它没有谈论字符串的内部字符数组。
-
@JoopEggen:没明白你的意思。能否请您详细说明一下。
标签: java string memory permgen