Unguarded Super Finalize Call

ID

java.super_finalize_in_finally

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

CWE:568, reliability

Description

Reports a void finalize() override that does not guarantee a call to super.finalize(): the call is either missing entirely, or present somewhere other than a finally block.

Rationale

If a finalize() override’s own cleanup throws before an unguarded super.finalize() call is reached, the parent class’s finalizer — and whatever resources it releases — never runs. Putting the call in a finally block guarantees it executes regardless of what happens in the rest of the method.

// Bad -- super.finalize() is skipped if close() throws
@Override
protected void finalize() throws Throwable {
    stream.close();
    super.finalize();
}

A final finalize() override with an empty body is exempt: it is the accepted defence against the finalizer attack, deliberately left with no cleanup at all.

Remediation

Move the call to super.finalize() into a finally block wrapping the override’s own cleanup.

// Good -- super.finalize() always runs
@Override
protected void finalize() throws Throwable {
    try {
        stream.close();
    } finally {
        super.finalize();
    }
}

© 2026 Xygeni. All rights reserved