Keep the finalize()
Method Protected When Overriding
What is it?
This practice is triggered when the finalize()
method is overridden with a public access modifier, which deviates from its intended protection level.
Why apply it?
The Object.finalize()
method is meant exclusively for the Garbage Collector to call. Making it public misleads clients into believing they can or should invoke it directly, potentially leading to misuse and creating security vulnerabilities.
How to fix it?
Override the finalize()
method with a protected
modifier, ensuring it remains inaccessible from outside the class or package.
Examples
Example 1:
Negative
In this negative example, finalize()
is overridden with a public
modifier, allowing unintended access.
public class MyResource {
@Override
public void finalize() throws Throwable { /* Noncompliant */
try {
// Resource cleanup logic
System.out.println("Cleaning up resources");
} finally {
super.finalize();
}
}
}
Example 2:
Positive
In this positive example, finalize()
is overridden with a protected
modifier, maintaining its restricted access.
public class MyResource {
@Override
protected void finalize() throws Throwable { /* Compliant */
try {
// Resource cleanup logic
System.out.println("Cleaning up resources");
} finally {
super.finalize();
}
}
}
Negative
The finalize()
method in this example is incorrectly public, offering unauthorized public access.
public class CacheManager {
@Override
public void finalize() throws Throwable { /* Noncompliant */
try {
// Perform cleanup of cache
System.out.println("Finalizing cache cleanup");
} finally {
super.finalize();
}
}
}
Example 3:
Positive
Here, finalize()
is correctly overridden with a protected
access level to prevent external access.
public class CacheManager {
@Override
protected void finalize() throws Throwable { /* Compliant */
try {
// Perform cleanup of cache
System.out.println("Finalizing cache cleanup");
} finally {
super.finalize();
}
}
}