字符串创建和字符串数组内存分配

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文字也使用堆空间[这是我从未读过的东西].

par*_*fal 2

从这个输出中可以清楚地看出,无论字符串是如何创建的,如果字符串具有相同的值,那么它们共享相同的 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对象,而不引用其字符数组。