在Java中,当对象没有实时引用时,就可以进行垃圾回收。现在,如果是字符串,则不是这种情况,因为该字符串将进入字符串池,并且JVM将使该对象保持活动状态以供重用。因此,这意味着一旦创建了字符串,“永远”不会被垃圾回收?
Answers:
现在,如果是字符串,则不是这种情况,因为字符串将进入字符串池,并且JVM将使对象保持活动状态以便重新使用。因此,这意味着一旦创建了字符串,“永远”不会被垃圾回收?
首先,只有字符串文字(请参见注释)会被自动插入/添加到字符串池中。 String
应用程序在运行时创建的对象不会被阻止...除非您的应用程序显式调用String.intern()
。
其次,实际上,在字符串池中垃圾回收对象的规则与其他String
对象(实际上是所有对象)相同。如果GC发现它们不可达,将对它们进行垃圾收集。
实际上,String
对应于字符串文字的对象通常不会成为垃圾回收的候选对象。这是因为在使用文字的每个方法的代码中都有对对象的隐式引用String
。这意味着String
只要方法可以执行,就可以访问。
但是,并非总是如此。如果在动态加载的类(例如使用Class.forName(...)
)中定义了字符串文字,则可以安排该类被卸载。如果发生这种情况,则String
对应于文字的对象可能无法访问,并最终被GC处理。
另请参阅:Java何时以及如何收集类垃圾?
笔记:
字符串文字(JLS 3.10.5)是Java源代码中出现的字符串; 例如
"abc" // string literal
new String(...) // not a string literal
也可以插入通过评估(编译时)常量表达式(JLS 15.28)而产生的字符串。
"abc" + 123 // this is a constant expression
严格来说,并不是所有的String文字都被嵌入。如果String文字仅在源代码中作为常量表达式的子表达式出现,则该文字可能不会以任何形式出现在“ .class”文件中。这样的文字不会被插入,因为它在运行时将不存在。
在Java 7之前,字符串池位于PermGen中。对于某些Java版本,如果选择了CMS收集器,则默认情况下不会启用PermGen的垃圾收集。但是CMS从来不是默认的收集器,并且有一个标记来启用CMS的PermGen收集。(而且没有人应该再为Java 6和更早版本开发代码。)
你是对的; 实习生池中的字符串将永远不会被GC。
但是,大多数字符串都没有被拘禁。
字符串文字是interned,传递到String.intern()
的字符串是intern,但其他所有字符串都不是internated,可以正常地进行GC处理。
new
将不会被插入。表示字符串文字的String对象将被实习。
字符串池中的字符串对象将不会被垃圾回收。如果您在程序执行中没有引用其他String对象,则将对其进行垃圾回收。
您可能会询问哪些字符串对象进入字符串池。字符串池中的对象是:
编译时间文字(例如String s1 = "123";
)
运行时中的Interstring对象(例如String s2 = new String("test").intern();
)
双方s1
并s2
在字符串池中引用的String对象。
任何在运行时创建但未进行实习的对象都将充当普通对象并驻留在堆内存中。这些对象可以被垃圾收集。
例如: String s3 = s1 + s2;
在这里,s3
引用了一个字符串对象,该对象与其他对象(不在字符串池中)一起位于堆内存中。