如何使用匿名对象,例如在返回语句的情况下使用:
return new JsonObject().put("name","xyz")
在堆中分配?由于他们没有任何命名引用,垃圾收集器如何从内存中清除它们?我试着寻找答案,但找不到答案,所以在这里张贴。
答案 0 :(得分:2)
如果某个实例在代码中不可用(可访问),那么它已经死了。当gc运行时,它会识别实时集,而不是死对象集。 JVM有自己的跟踪活动对象的方式。
收集器将跟踪实时集,标记所有活动对象。
然后收集器将根据类型将实时集移动到另一个内存区域(复制收集器)或遍历堆,在找到它们时删除死对象并可选择压缩堆。
在您的特定情况下,匿名对象没有特定引用的事实对gc来说并不重要,因为它有跟踪实时和死对象的方式。
答案 1 :(得分:1)
这里也有类似的问题; Inner Class has an implicit reference to the outer class and may can leak memory以及http://viralpatel.net/blogs/inner-classes-in-java/
中非常好的描述注意这一行;
内部类的对象具有对实例化它的外部类对象的隐式引用。
您可以通过简单的测试看到这一点;
public class Frame1
{
public class JsonObject
{
int field1 = 123;
int field2 = 456;
public JsonObject() { }
}
// code that callSomething()
// ...
private Object callSomething()
{
return new JsonObject();
}
}
我在返回行上添加了一个断点,并允许代码步进足够远以便创建JsonObject。然后附上JVisualVM并查看我看到的堆上唯一的JsonObject实例;
有一个对外Frame1
类