危险的 runFinalizersOnExit¶
ID: java/run-finalizers-on-exit
Kind: problem
Security severity:
Severity: error
Precision: medium
Tags:
- reliability
- maintainability
Query suites:
- java-security-and-quality.qls
避免调用 System.runFinalizersOnExit
或 Runtime.runFinalizersOnExit
,它们被认为是危险的方法。
Java Development Kit 文档中关于 System.runFinalizersOnExit
的说明
此方法本质上不安全。它可能导致对活动对象调用终结器,而其他线程同时操作这些对象,从而导致不稳定行为或死锁。
对象终结器通常仅在垃圾回收器即将回收对象时调用。使用 runFinalizersOnExit
会设置一个 Java 虚拟机范围的标志,在运行时退出之前对所有带有 finalize
方法的对象执行终结器。这将要求所有带有终结器的对象防止在对象仍在使用时调用 finalize
,这对大多数应用程序来说不切实际。
建议¶
确保代码不依赖于终结器的执行。如果代码依赖于 Java 虚拟机的垃圾回收行为,则无法保证终结器将及时执行,甚至根本不会执行。如果终结器用于处置有限的系统资源(例如文件句柄),这可能会成为问题。
使用显式 dispose
方法(而不是终结器)在 finally
块中,以确保释放对象的资源。
示例¶
以下示例显示了一个调用 runFinalizersOnExit
的程序,不建议这样做。
void main() {
// ...
// BAD: Call to 'runFinalizersOnExit' forces execution of all finalizers on termination of
// the runtime, which can cause live objects to transition to an invalid state.
// Avoid using this method (and finalizers in general).
System.runFinalizersOnExit(true);
// ...
}
以下示例显示了建议的方法:一个在 finally
块中调用 dispose
方法的程序。
// Instead of using finalizers, define explicit termination methods
// and call them in 'finally' blocks.
class LocalCache {
private Collection<File> cacheFiles = ...;
// Explicit method to close all cacheFiles
public void dispose() {
for (File cacheFile : cacheFiles) {
disposeCacheFile(cacheFile);
}
}
}
void main() {
LocalCache cache = new LocalCache();
try {
// Use the cache
} finally {
// Call the termination method in a 'finally' block, to ensure that
// the cache's resources are freed.
cache.dispose();
}
}
参考¶
J. Bloch,Effective Java(第二版),第 7 项。Addison-Wesley,2008 年。
Java API 规范:System.runFinalizersOnExit(),Object.finalize()。
Java API 规范:Java 线程基元弃用。