终结器不一致¶
ID: java/missing-super-finalize
Kind: problem
Security severity:
Severity: error
Precision: medium
Tags:
- reliability
- maintainability
- external/cwe/cwe-568
Query suites:
- java-security-and-quality.qls
一个 finalize
方法覆盖了超类的终结器,但没有调用 super.finalize
,可能会导致系统资源未释放或导致其他清理操作未完成。
建议¶
确保所有 finalize
方法都调用 super.finalize
,以确保执行其超类的终结器。在 Java 中,终结器链接不是自动的。
还可以通过将清理代码放入终结器守护程序而不是 finalize
方法中来防御不调用 super.finalize
的子类。终结器守护程序是一个匿名对象实例,它在其 finalize
方法中包含用于封闭对象的清理代码。对终结器守护程序的唯一引用存储在封闭实例的私有字段中,这意味着守护程序和封闭实例可以同时被终结。这样,子类无法通过不调用 super.finalize
来阻止执行清理代码。
示例¶
在以下示例中,WrongCache.finalize
没有调用 super.finalize
,这意味着本机资源未释放。但是,RightCache.finalize
确实调用了 super.finalize
,这意味着本机资源已释放。
class LocalCache {
private Collection<NativeResource> localResources;
//...
protected void finalize() throws Throwable {
for (NativeResource r : localResources) {
r.dispose();
}
};
}
class WrongCache extends LocalCache {
//...
@Override
protected void finalize() throws Throwable {
// BAD: Empty 'finalize', which does not call 'super.finalize'.
// Native resources in LocalCache are not disposed of.
}
}
class RightCache extends LocalCache {
//...
@Override
protected void finalize() throws Throwable {
// GOOD: 'finalize' calls 'super.finalize'.
// Native resources in LocalCache are disposed of.
super.finalize();
}
}
以下示例显示了一个终结器守护程序。
class GuardedLocalCache {
private Collection<NativeResource> localResources;
// A finalizer guardian, which performs the finalize actions for 'GuardedLocalCache'
// even if a subclass does not call 'super.finalize' in its 'finalize' method
private Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
for (NativeResource r : localResources) {
r.dispose();
}
};
};
}
参考¶
Java API 规范:Object.finalize()。
J. Bloch,Effective Java(第二版),第 7 项。Addison-Wesley,2008 年。
常见弱点枚举:CWE-568。