Mismatched Finalizer Signature
ID |
java.no_overload_finalize |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
best-practice, reliability |
Description
Reports a method named finalize whose signature is not void finalize().
Only that exact signature overrides Object.finalize(). A method that adds a parameter, or returns a value, is an unrelated method that happens to share the name — and the garbage collector will never call it.
Rationale
class DraftReport {
private int revision;
void finalize(int nextRevision) { // an overload, not the finalizer
revision = nextRevision;
}
}
class SummaryReport {
private int total;
private int finalize() { // right parameters, wrong return type
return total;
}
}
Both methods are dead weight in practice. The collector will not invoke them, because neither overrides the finalizer. Callers will not invoke them either, because a method called finalize reads as something the runtime owns. Any cleanup written inside silently never runs, and a reader auditing the class for resource handling is actively misled.
The second form only compiles because a private method does not participate in overriding — which is exactly what makes it easy to miss in review.
Remediation
Give the method a name that says what it does. The confusion disappears and the method becomes callable:
class DraftReport {
private int revision;
void applyRevision(int nextRevision) {
revision = nextRevision;
}
}
If the intent really was to hook object teardown, do not use finalization: it runs at an unpredictable time, may never run at all, and swallows exceptions. Implement AutoCloseable and let callers use try-with-resources, or register the resource with a java.lang.ref.Cleaner.