java字符串文字可以被垃圾收集吗? 如果是,如何certificate?

"abc"这样的java 字符串文字可以被垃圾收集吗? 如果是,我们如何以编程方式certificate他们是GCed?

是的,发布Java7,如果加载它的类加载器被垃圾收集并且没有对字符串文字的引用,则可以对字符串文字进行垃圾收集。

注意:在Java -8中,您必须调用GC两次以确保ClassLoaders获得GCed(Metaspace .. pfff ..使用不同的GC将无济于事)。

 Case -1 : //ClassLoaders don't get GCed. Code : import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; // main class class TestStringLiteralGC { public static void main(String[] args) throws Exception { Class c1 = new CustomClassLoader().loadClass("Test"); // load class once Class c2 = new CustomClassLoader().loadClass("Test"); // load class again System.out.println("c1 : " + c1); // c1 : class Test System.out.println("c2 : " + c2); // c2 : class Test System.out.println("c1 == c2 :" + (c1 == c2)); //c1 == c2 :false --> So, now we have 2 different class objects for same class. Field f1 = c1.getDeclaredField("s"); // getting field s of c1 f1.setAccessible(true); System.out.println("Identity hashCode of c1.s :"+ System.identityHashCode(f1.get(null))); // Identity hashCode of c1.s :1442407170 Field f2 = c2.getDeclaredField("s"); // getting field s of c2 f2.setAccessible(true); System.out.println("Identity hashCode of c2.s :"+ System.identityHashCode(f2.get(null))); // Identity hashCode of c2.s :1442407170 System.out.println("c1.s == c2.s : " + (f1.get(null) == f2.get(null))); // c1.s == c2.s : true ==> c1.s is the same "instance" as c2.s //Don't make c1 and c2 eligible for GC // So, now, there are still references to "abc" // f1 = null; // c1 = null; // f2 = null; // c2 = null; //call GC explicitly. Yes, twice. Thread.sleep(1000); System.gc(); Thread.sleep(1000); System.gc(); Thread.sleep(1000); // use the same string literal in main. Just to test that the same literal is being used. String s = "abc"; System.out.println("Identity hashCode of mainMethod's s : " + System.identityHashCode(s)); // Identity hashCode of mainMethod's s : 1442407170 ==> Yes. The IDHashcodes are the same } } // Our class which will be loaded class Test { static String s = "abc"; // Our little hero!.The string literal. } //Our custom ClassLoader to load the class "Test" class CustomClassLoader extends ClassLoader { // finalize() is to check if Object is unreachable (and ready for GC) protected void finalize() throws Throwable { System.out.println("CustomClassLoader finalize called.." + this); }; @Override public Class loadClass(String name) throws ClassNotFoundException { if (!name.equals("Test")) { return super.loadClass(name); } try { InputStream in = ClassLoader .getSystemResourceAsStream("Test.class"); byte[] a = new byte[10000]; int len = in.read(a); in.close(); return defineClass(name, a, 0, len); } catch (IOException e) { throw new ClassNotFoundException(); } } } O/P : // NO GC of Classloaders :( c1 : class Test c2 : class Test c1 == c2 :false Identity hashCode of c1.s :1442407170 // Value- 1 Identity hashCode of c2.s :1442407170 // Value -2 c1.s == c2.s : true Identity hashCode of mainMethod's s : 1442407170 // Value -3 

(1,2)和3的相同IdentityHashCode表示在所有3个位置使用相同的字符串文字“abc”。

 Case : 2 //Force GC of ClassLoaders and check again. Code : import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; // main class class TestStringLiteralGC { public static void main(String[] args) throws Exception { Class c1 = new CustomClassLoader().loadClass("Test"); // load class once Class c2 = new CustomClassLoader().loadClass("Test"); // load class again System.out.println("c1 : " + c1); // c1 : class Test System.out.println("c2 : " + c2); // c2 : class Test System.out.println("c1 == c2 :" + (c1 == c2)); //c1 == c2 :false --> So, now we have 2 different class objects for same class. Field f1 = c1.getDeclaredField("s"); // getting field s of c1 f1.setAccessible(true); System.out.println("Identity hashCode of c1.s :"+ System.identityHashCode(f1.get(null))); // Identity hashCode of c1.s :1442407170 Field f2 = c2.getDeclaredField("s"); // getting field s of c2 f2.setAccessible(true); System.out.println("Identity hashCode of c2.s :"+ System.identityHashCode(f2.get(null))); // Identity hashCode of c2.s :1442407170 System.out.println("c1.s == c2.s : " + (f1.get(null) == f2.get(null))); // c1.s == c2.s : true ==> c1.s is the same "instance" as c2.s //Make c1 and c2 eligible for GC // So, now, there are no references to "abc" f1 = null; c1 = null; f2 = null; c2 = null; //call GC explicitly. Yes, twice. Thread.sleep(1000); System.gc(); Thread.sleep(1000); System.gc(); Thread.sleep(1000); // use the same string literal in main. Just to test that the same literal is being used. String s = "abc"; System.out.println("Identity hashCode of mainMethod's s : " + System.identityHashCode(s)); // Identity hashCode of mainMethod's s : 1118140819 ==> Oh!!. The IDHashcodes are NOT the same } } // Our class which will be loaded class Test { static String s = "abc"; // Our little hero!.The string literal. } //Our custom ClassLoader to load the class "Test" class CustomClassLoader extends ClassLoader { // finalize() is to check if Object is unreachable (and ready for GC) protected void finalize() throws Throwable { System.out.println("CustomClassLoader finalize called.." + this); }; @Override public Class loadClass(String name) throws ClassNotFoundException { if (!name.equals("Test")) { return super.loadClass(name); } try { InputStream in = ClassLoader .getSystemResourceAsStream("Test.class"); byte[] a = new byte[10000]; int len = in.read(a); in.close(); return defineClass(name, a, 0, len); } catch (IOException e) { throw new ClassNotFoundException(); } } } O/P : c1 : class Test c2 : class Test c1 == c2 :false Identity hashCode of c1.s :1442407170 // Value - 1 Identity hashCode of c2.s :1442407170 // Value - 2 c1.s == c2.s : true CustomClassLoader finalize called..CustomClassLoader@4e25154f // ClassLoader1 GCed CustomClassLoader finalize called..CustomClassLoader@6d06d69c // ClassLoader2 GCed Identity hashCode of mainMethod's s : 1118140819 // Value - 3 .. 

(1,2)和3的IdentityHashCodes是不同的。 因此,“main”方法中使用的字符串“abc”与由2个不同的类加载器加载Test时添加到字符串常量池的字符串文字“abc”不同。

一种简单的certificate方法是使用分析器 。 通过分析器,您可以查看应用程序内存中的所有对象。