Empty Finalizer Body

ID

java.no_empty_finalizer

Severity

high

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Efficiency

Language

Java

Tags

best-practice, efficiency

Description

Reports a finalize() override whose body contains no statement. Comments are not statements, so a body holding only comments is reported as empty too.

An empty finalizer is not a harmless leftover. Declaring one makes the JVM register every instance of the type with the finalization queue, so those objects survive at least one extra collection cycle before their memory can be reclaimed — and nothing is released in return.

Rationale

class PageBuffer {
  private final byte[] page = new byte[64];

  @Override
  protected void finalize() {          // empty: costs a finalization round, releases nothing
  }
}

Every PageBuffer now goes through the finalizer thread before it can be collected. The class pays the whole cost of finalization for a method that does nothing.

Two shapes are not reported:

  • A final empty finalizer. An empty final finalize() is the accepted defence against the finalizer attack — it stops a subclass from installing a finalizer that could resurrect a partially constructed object, and the body has to stay empty for the idiom to work.

  • A method named finalize that takes parameters or returns a value. That is not the finalizer at all; a separate rule covers it.

Remediation

Delete the empty override. The type then follows the normal collection path with no finalization overhead:

class PageBuffer {
  private final byte[] page = new byte[64];
}

If cleanup really is needed, do not put it in a finalizer: finalization 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.

© 2026 Xygeni. All rights reserved