java中的字符串文字和垃圾收集器

时间:2014-05-29 12:58:10

标签: java garbage-collection

更具体地说,我已经读过,在java 7中,字符串文字现在存储在堆的主要部分中,那么它们是否符合垃圾收集器的条件?

String a ="z";
a = null;

现在对象“z”是垃圾收集,还是作为匿名对象仍然在字符串池中?

2 个答案:

答案 0 :(得分:1)

字符串文字只能在包含这些文字的所有类都是GCed时进行GCed,而这只能在加载这些类的ClassLoader被GCed时才会发生。

示例:

public interface I {
    String getString();
}

public class Test2 implements I {
    String s = "X";
    @Override
    public String getString() {
        return s;
    }
}

public class Test implements I {
    String s = "X";
    @Override
    public String getString() {
        return s;
    }
}

public class Test1 {

    public static void main(String[] args) throws Exception {
        ClassLoader cl = new URLClassLoader(new URL[] {new URL("file:d:/test/")});
        I i = (I)cl.loadClass("Test").newInstance();
        WeakReference w = new WeakReference(i.getString()); //weak ref to "X" literal
        i = null;
        cl = null;
        System.out.println(w.get());
        System.gc();
        Thread.sleep(1000);
        System.out.println(w.get());
    }
}

编译这些类,将Test.class移动到d:/ test,以便系统类加载器无法看到它,然后运行main。你会看到

X
null

表示“X”是GC编辑

答案 1 :(得分:0)

  • 等效字符串文字(甚至是那些存储在单独的类中的文字 单独的包)将引用相同的String对象。

  • 通常,String Literals不符合垃圾回收的条件。 的自从

  • 在运行时创建的字符串将始终与这些字符串不同 从String Literals创建。

  • 通过使用,可以将String Literals与运行时字符串重用 intern()方法。

  • 检查字符串相等性的最佳方法是使用equals() 方法

资料来源:
http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html

请注意,这有点高级 - 您必须了解类String的内部工作原理才能理解这一点。

String对象将其数据存储在字符数组中。当您获取字符串的子字符串时,通过调用substring()方法,然后创建的新String对象不会复制原始字符串的部分数据。相反,它存储对原始字符串的基础数据的引用,以及偏移量和长度,以指示新String对象所代表的旧字符串的哪一部分。

当你有一个非常长的字符串(例如你将文件的内容读入String对象)并从中取出一个子字符串时,JVM会将原始字符串的所有数据保留在内存中 - 甚至如果丢弃原始的String对象,因为使用substring()创建的String对象仍然包含对包含所有数据的整个字符数组的引用。

为了防止此内存效率低下,您可以使用substring对象显式创建一个新的String对象。第二个新的String对象将复制子串对象中的数据,但只复制您需要的部分。 查看plainprint? 注意:代码块中的文本内容是自动换行的

// Suppose this contains 100K characters read from a file  
String largeString = ...;  

// This will refer to the 100K char array from largeString, keeping the whole buffer in memory  
// even though sub represents only 20 characters  
String sub = largeString.substring(80, 100);  

// This will copy the 20 characters from sub into a new buffer, so that the whole 100K buffer doesn't need to be kept  
String sub2 = new String(sub);  

如果你想看看它是如何工作的,那么看一下String类的源代码,你可以在JDK安装目录的src.zip文件中找到它。

资料来源:
http://www.coderanch.com/t/542489/java/java/string-literal-String-Object