字符串池 - 字符串对象 - 垃圾收集

时间:2014-12-16 10:08:31

标签: java string garbage-collection

Garbage Collection在以下情况下的工作方式感到困惑。考虑下面的代码。

String s1 = "abc"; // s1 points to "abc"
String s2 = s1;   // s2 points to "abc"
String s3 = "abc1"; // s3 points to "abc1"

s1 = s3; // s1 points to "abc1"
s2 = null;  // s2 reference is removed, "abc" is no longer referenced now

在此之后,"abc"将有资格获得GC

如果上面的例子相同,如果我使用new String()

String s1 = new String("abc");

现在会有什么结果。

还有任何工具,通过我们可以监视垃圾收集,因为GC收集了对象

5 个答案:

答案 0 :(得分:3)

在第一种情况下

 String s1 = "abc"

你的字符串将进入由JVM维护的字符串池中,并且永远不会被垃圾收集。

然而在第二种情况下

 String s1 = new String("abc");

通用规则适用,并且您的字符串对象将在其范围结束后立即收集垃圾。

答案 1 :(得分:2)

您可以使用Oracle自身提供的Visual VM来监控许多内容,包括内存。

获得洞察力的另一个小黑客。考虑下面的代码。

String a = "abc"

String b = "abc"

如果我们做a==b比较引用,它实际上将返回true,因为Java知道abc是相同的,它将被引用到String池中的相同内存。

因此,当没有对字符串的引用时,它是GC完成工作的线索。

答案 2 :(得分:2)

答案 3 :(得分:1)

String s1 = "abc"; // s1 points to "abc" 这里,“abc”将添加到字符串常量池中,并且通常不会被GCed。任何字符串文字(在双引号内)通常都不会被GCed。

String s1 = new String(“abc”);

以上行创建了2个字符串。 “abc”将被添加到String常量池中(假设它已经不存在),并且另一个值为“abc”的String将在堆上。存在于堆上的String对象一旦变为 unreachable 就可以被GC(即,没有对它的引用)

答案 4 :(得分:0)

嗯,它并不像听起来那么简单。答案取决于您正在使用的Java版本。 可以在编译时解析的所有字符串文字(如示例中的那些)都来自字符串常量池,基本上是在JVM开头创建的HashTable,并在加载类时更新。

如果您正在使用Java 6,那么此字符串常量池是PermGen的一部分,PermGen是堆外部的空间,但由java进程管理。就像Heap一样,GC在这个地区不会被触发,直到它满了。除非你处理数百万个课程或者你的PermGen规模非常小,否则这个地区不会很快填满,GC也不会经常出现。所以回答你的问题,即使在删除所有对" abc"的引用之后,它也不会成为GC,直到PermGen填满。

从Java7开始,字符串常量池也是Heap的一部分,因此您的对象分配率可能会影响GC的频率和" abc"可能会比在Java6中更早清除。

没有特定的工具来检查哪些对象是GC,但我们有一些标准JDK附带的很酷的工具,这将有助于我们更好地理解GC和内存消耗并进行调整< / p>

VisualVM - 有一个名为VisualGC的插件 - 通过这个你可以了解GC中的趋势

Java Mission Control中的

FlightRecorder 显示有关GC和内存消耗的更多数据,而不是VisualVM

如果您需要更多信息,请查看此link:)