Lok*_*esh 6 java memory string permgen
在创建String时,我已经阅读了很多关于内存分配的相互矛盾的文章.有些文章说新的运算符在堆中创建一个String,而String literal是在String Pool [Heap]中创建的,而有些人则说新运算符在堆中创建一个对象而另一个对象在String池中创建.
为了分析这个,我编写了下面的程序,它打印了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);
}
}
Run Code Online (Sandbox Code Playgroud)
该程序打印以下输出:
Analyse s1
1569228633
778966024
Analyse s2
1569228633
1021653256
Analyse s3
1569228633
1794515827
Analyse s4
1569228633
1794515827
Run Code Online (Sandbox Code Playgroud)
从这个输出中可以清楚地看出,无论String如何创建,如果字符串具有相同的值,则它们共享相同的char数组.
现在我的问题是这个chararray存储在哪里,是存储在堆中还是存在于permgen?另外,我想了解如何在堆内存地址和permgen内存地址之间进行区分.
我有一个很大的问题,如果它存储在permgen,因为它会占用我珍贵的有限的permgen空间.如果char数组没有存储在permgen中而是存储在堆中,那么它是否意味着String文字也使用堆空间[这是我从未读过的东西].
从这个输出中可以清楚地看出,无论字符串是如何创建的,如果字符串具有相同的值,那么它们共享相同的 char 数组
不完全是:发生这种情况是因为您从一个文字字符串开始,并从中创建多个实例。在 OpenJDK (Sun/Oracle) 实现中,如果支持数组代表整个字符串,则将复制它。您可以在src.jar或此处查看: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java#String.%3Cinit% 3E%28java.lang.String%29
如果您仔细构建源字符串,使它们从不同的字符数组开始,您会发现它们不共享支持数组。
现在我的问题是这个字符数组存储在哪里
据我所知,字符串文字的字符数组存储在堆上(那些对类加载内部结构有更好了解的人,请随意发表评论)。从文件加载的字符串将始终将其支持数组存储在堆上。
我确实知道的是,所使用的数据结构intern()仅引用String对象,而不引用其字符数组。
| 归档时间: |
|
| 查看次数: |
2576 次 |
| 最近记录: |