给我一个方法并询问,当它符合垃圾收集资格时,我的意思是在哪一行。我相信o
和oa
都有资格进行垃圾回收。因为,它们被设置为null
。如果我错了,请纠正我。但是,问题是,当它符合gc
的条件时,我的意思是在哪一行。 ?
public Object m() {
Object o = new Float(3.14F);
Object[] oa = new Object[1];
oa[0] = o; /* Line 5 */
o = null; /* Line 6 */
oa[0] = null; /* Line 7 */
return o; /* Line 8 */
}
请有人解释。 ?
答案 0 :(得分:4)
让我们来看看代码:
1) o = new Float();
2) oa = new Object[];
at this point we have 2 objects.
3) oa[0] = o;
at this point oa[0] holds the reference of o.
4) o = null;
o is still being referenced by oa[0]
5) oa[0] = null
o now has zero references.
6) return o;
o is null.
第7行是o
的GC资格。在函数退出之前,oa
不符合GC条件。
通常,只有在没有引用的情况下,对象才有资格使用GC。在处理String
时要非常小心,因为有一个叫做字符串池的特殊地方。所以下面的代码:
void foo()
{
String s = "foo";
s=null;
return s;
}
s
绝不保证符合该职能的条件。
评论问题
一个问题,你说..在功能之前,没有资格获得GC 退出。但是,在返回o之前,oa设置为null并且无处可去 转介
答案:
oa未设置为null。设置为null的是oa [0]处的对象 (oa的第一个索引)。如果该行为oa = null则为真, 并且无论oa中的唯一项目是否为null,实际上都不是 使包装器(在本例中为数组)为null。类似于拥有 列出并清空其所有元素不会使List为空。
答案 1 :(得分:3)
允许Java进行某些优化,因此仅针对局部效应的优化JIT可以简化此代码
public Object m() {
//Object o = // o does not participate in any externally visible side-effect
new Float(3.14F); // Available for collection as soon as ctor finishes.
//Object[] oa = new Object[1]; // Array ctors are known not to have side-effects, and oa does not participate in a side-effect or result that is visible outside the method.
//oa[0] = o; /* Line 5 */ // Side-effect not visible.
// o = null; /* Line 6 */ // Side-effect not visible.
//oa[0] = null; /* Line 7 */
//return o; /* Line 8 */ // Eliminated by inlining.
return null; // Type-analysis proves that this method can only return null.
}
不要假设局部变量到null
的赋值实际上发生在长期方法调用中。
答案 2 :(得分:1)
当不再引用该对象时,垃圾收集符合条件,但重要的是要注意GC不能保证在那时运行,因此从技术上讲,可以分配内存。
oa [0]引用该对象,因此当您在第7行将其设置为null时,不再存在对该对象的引用,因此它符合GC的条件。
正如评论所指出的那样,oa,数组本身仍然存在,直到方法执行完毕,即在第8行执行之后。它在方法m()的生命周期中是本地的,因此当m()从执行返回时它将符合GC的条件。
答案 3 :(得分:0)
如果我错了,请纠正我。但是,问题是,当它有资格获得gc时,我的意思是在哪一行。 ?
这个问题是荒谬的,或者基于过度简化的垃圾收集模型。垃圾收集器在运行时对可用表示进行操作,这意味着从全局根(包括寄存器,堆栈和全局变量)跟踪可达性。与高级源代码没有对应关系,因此询问行号是没有意义的。实际上,在GC运行之前,编译器会将您的代码变得无法识别。
答案 4 :(得分:-1)
AFAIK,Java使用Mark-And-Sweep算法。 GC反复在堆上的单独线程中运行。
如果某个参考变量(或对象)超出范围,则标记为删除并在适当时(或覆盖)清除。
每当变量设置为null时,即静态引用和其他线程的引用计数对象变为无法访问时,即其引用不再存在时,它标记为再次删除。
代码中的第7行是将其标记为删除的位置。