请考虑以下代码:
public class Leaky {
public static LongLive instance = new LongLive();
static class LongLive {
public void create() {
}
}
static class Victim {
final LongLive factory;
public Victim() {
/** Hold strong reference to static instance */
System.out.println("Create new child..");
factory = instance;
}
@Override
protected void finalize() throws Throwable {
System.out.println("About to get gc-ed?");
super.finalize();
}
}
static void sleep(int sec) {
try {
Thread.sleep(sec * 1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; ++i) {
final Victim c = new Victim();
System.gc();
sleep(1);
}
}
}
根据我的理解,任何Victim
对象都不应该被gc-ed,因为它保留了对instance
对象的强引用,该对象只要程序运行就存在。但是,我确实看到打印出“即将获得gc-ed”。有人能帮我解释一下吗?
答案 0 :(得分:2)
Victim
得到gc-ed因为没有引用指向它们,所以它们可以被安全地gc-ed,因为没有人能够再次使用它们(在每次迭代后你都会失去对它的引用)最后Victim
因为您将其分配给for
循环内的变量。
他们所指的并不重要。重要的是谁指向他们。
内存泄漏的典型情况是堆栈的这种实现。
public class Stack {
Object[] st = new Object[100];
int top;
public void push(Object o) {
// Not checking boundaries for simplicity.
st[top++] = o;
}
public Object pop() {
return st[--top];
}
}
请注意,弹出后,存储在数组中的元素仍然存在,除非您将位置设置为null
或其他元素覆盖它们,否则这些元素将不会被gc-ed