我在网站How is the java memory pool divided?上阅读了这个问题,我想知道这些扇区中的哪一个是"字符串常量池"属于?
池中的String
文字是否也得到了GC?
intern()
方法从池中返回String
文字的基本链接。
如果池确实获得了GCed,那么它对于字符串池的想法是否会适得其反?将再次创建新的String
文字,从而使GC无效。
(假设池中只存在一组特定的文字,它们永远不会过时,迟早会再次需要它们)
答案 0 :(得分:2)
据我所知,字符串文字最终出现在非堆JVM内存的“Perm Gen”部分。只在全GC运行期间(非部分)检查Perm Gen空间。
在早期的JVM中(我承认我必须查看它,因为我不确定),字符串池never got GC中的字符串文字。在较新的JVM中,WeakReferences用于引用池中的字符串,因此实际的字符串实际上可以获取GC,但仅限于完全垃圾收集期间。
答案 1 :(得分:1)
为String.intern()读取JavaDoc并没有给出实现提示,但根据this page,实习字符串由弱引用保存。这意味着如果GC检测到除了保存实际字符串的存储库之外没有对实习字符串的引用,则允许它们收集它们。当然这对外部代码是透明的,所以除非你使用自己的弱引用,否则你永远不会知道垃圾收集。
答案 2 :(得分:1)
字符串合并
字符串池(有时也称为字符串规范化)是一种 用相同的值替换几个String对象的过程但是 具有单个共享String对象的不同标识。你可以实现 保持自己的地图(可能是软的) 或弱参考,取决于您的要求)和使用地图 值作为规范化的值。或者您可以使用String.intern()方法 由JDK提供给您。
在Java 6时,许多人禁止使用String.intern() 标准是由于很有可能获得OutOfMemoryException,如果 汇集失控。 Oracle Java 7实现字符串 汇集已大大改变。你可以查找详细信息 http://bugs.sun.com/view_bug.do?bug_id=6962931和 http://bugs.sun.com/view_bug.do?bug_id=6962930
Java 6中的String.intern()
Java 7中在那些美好的旧时代,所有实习字符串都存储在PermGen中 - 堆的固定大小部分主要用于存储加载的类 和字符串池。除了明确的实习字符串,PermGen字符串 pool还包含程序中先前使用的所有文字字符串 (这里使用的重要词 - 如果一个类或方法永远不会 加载/调用,其中定义的任何常量都不会被加载。
Java 6中这种字符串池的最大问题是它的位置 - PermGen。 PermGen具有固定的大小,无法扩展 运行。您可以使用-XX:MaxPermSize = 96m选项进行设置。就我而言 知道,默认的PermGen大小在32M到96M之间变化,具体取决于 该平台。你可以增加它的大小,但它的大小仍然是 固定。这种限制需要非常小心地使用String.intern - 你最好不要使用这种方法实习任何不受控制的用户输入。 这就是为什么Java 6时代的字符串池主要实现的原因 手动管理的地图。
String.intern()
Oracle工程师对字符串进行了非常重要的更改 Java 7中的池化逻辑 - 字符串池被重定位到堆中。 这意味着您不再受限于单独的固定尺寸 记忆区。所有字符串现在都位于堆中,与其他大多数字符串一样 普通对象,它允许您只管理堆大小 调整你的申请。从技术上讲,仅此一点就足够了 有理由重新考虑在Java 7程序中使用String.intern()。 但还有其他原因。
字符串池值是垃圾回收
是的,JVM字符串池中的所有字符串都有资格使用垃圾 如果程序根目录中没有对它们的引用,则为集合。 它适用于所有讨论过的Java版本。这意味着,如果你的 实习字符串超出范围,没有其他引用 它 - 它将从JVM字符串池中收集垃圾。
有资格进行垃圾收集并驻留在堆中,即JVM 字符串池似乎是所有字符串的正确位置,不是吗? 理论上确实如此 - 未使用的字符串将被垃圾收集 池,使用的字符串将允许您保存内存以防万一 从输入中获取一个相等的字符串。似乎是一个完美的记忆 储蓄策略?几乎如此。您必须知道字符串池是如何的 在做出任何决定之前实施。
答案 3 :(得分:0)
String
文字不会在运行时创建到池中。我不确定他们是否得到了GC,但我怀疑他们不是出于两个原因:
答案 4 :(得分:0)
尽管字符串是不可变的,但它们仍然是Java中的任何其他对象。在堆上创建对象,字符串也不例外。所以,Strings that are part of the "String Literal Pool" still live on the heap, but they have references to them from the String Literal Pool.
有关详情,请参阅此链接
`http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html`
新编辑:
public class ImmutableStrings
{
public static void main(String[] args)
{
String one = "someString";
String two = new String("someString");
one = two = null;
}
}
在main方法结束之前,有多少对象可用于垃圾回收? 0? 1? 2?
答案是1.与大多数对象不同,字符串文字总是从字符串文字池中引用它们。这意味着他们总是引用它们,因此不符合垃圾收集的条件。
我们的局部变量(一个或两个)都没有引用我们的String对象,但仍然有一个来自String Literal Pool的引用。因此,对象不能用于垃圾收集。通过使用intern()方法总是可以访问对象