问题描述
因此,根据我发现的许多答案,new String("abc");
在堆中创建了一个对象,在字符串池中创建了文字"abc"
。由于使用了new
关键字,因此池中不应引用String文字。
这意味着-
a。该文字将在下一次运行中进行GC处理(假设以后不会再创建其他对文字的引用)吗?
b。如果(对a的回答是)是,那么JVM在对象创建后立即释放池中的字面量就相当容易了,而不是等待GC。为什么不这样做?
c。如果(对a的回答为)否,那么将无法访问的文字不进行GC处理的原因是什么?
解决方法
由于使用了
new
关键字,因此池中不应引用String文字。
那是不正确的。可能有 1 对与文字对应的String
对象的可达引用。我的回忆是,引用存储在保存该类的静态字段的同一“框架”中。实际上,在垃圾收集器卸载封闭类之前,此引用将继续可用。 (通常通常不会发生。)
答案是:
a。该文字将在下一次运行中进行GC处理(假设以后不会再创建其他对文字的引用)吗?
否。
c。如果(对a的回答为)否,那么将无法访问的文字不进行GC处理的原因是什么?
与文字对应的String
对象不是不可访问的。例如,如果有可能再次执行new String("abc")
语句,则它必须是可到达的。
由于JVM运行时很难确定一个语句(在编译时被确定是可以到达的)在运行时不会被执行多次,并且由于这样做几乎没有性能优势,因此运行时假定,在定义它们的Java类 2 的生存期内,所有字符串文字都必须是可访问的。
最后,正如@Holger指出的那样,当String文字对象变得不可访问时,它没有任何实际区别。我们知道,如果需要它们会以某种形式出现。真的很重要。
1-实际行为在很大程度上取决于实现。在早期的JVM中,急切地插入了用于类文字的String对象。后来此更改为懒惰实习。甚至在每次使用字符串文字时都可以重新实习一个String对象,尽管通常这效率很低。然后,我们需要考虑优化器可以可以做的各种事情。例如,它可能会注意到文字的String
对象永远不会逃逸,并且其使用方式实际上不需要进行插值。或者它可能会注意到整个表达式可以被优化掉。
2-我的意思是上课。与Class
对象相对应的事物。不是这些类的实例。
因为新的String(“ abc”);是对象并且没有被拘禁,它将在下一次GC运行中被垃圾回收。
-
但是由于各种性能原因和可用空间,GC不会立即运行以仅收集此字符串对象。
-
使用System.gc();还不保证它会运行(这只是建议GC运行)。
GC运行的原因很多,如下所示(也取决于VM)
更多特定代中的内存分配失败了。 堆分配或对象存在达到阈值等。