Avoid Calling runFinalizersOnExit
in Java Applications
What is it?
This practice is triggered by the use of the System.runFinalizersOnExit
method, which is considered unsafe for predictable finalization of objects during JVM termination.
Why apply it?
Using runFinalizersOnExit
can lead to erratic behavior and deadlocks because finalizers might be called on live objects while other threads are actively using them. Instead, attach shutdown hooks which provide a more controlled and safe way to execute operations upon JVM shutdown.
How to fix it?
Replace the use of System.runFinalizersOnExit
with a shutdown hook registered with Runtime.getRuntime().addShutdownHook(Thread)
.
Examples
Example 1:
Negative
The negative example calls System.runFinalizersOnExit(true)
, leading to unsafe finalization of objects and potential deadlocks, which is a noncompliant approach.
public class UnsafeFinalizerExample {
public static void main(String[] args) {
System.runFinalizersOnExit(true); // Noncompliant
System.out.println("Application running...");
}
protected void finalize(){
System.out.println("Finalizing resources.");
// Finalization logic here
}
}
Example 2:
Positive
The positive example uses a shutdown hook to perform cleanup operations when the JVM is shutting down, ensuring safe and predictable finalization.
public class ShutdownExample {
public static void main(String[] args) {
Thread cleanupThread = new Thread(() -> {
System.out.println("Performing cleanup operations.");
performCleanupTasks();
});
Runtime.getRuntime().addShutdownHook(cleanupThread);
System.out.println("Application running...");
}
private static void performCleanupTasks() {
// Cleanup logic here
}
}
Negative
The negative example demonstrates the use of System.runFinalizersOnExit
which can lead to unpredictable application shutdown behavior, thus is noncompliant.
public class UnsafeShutdown {
public static void main(String[] args) {
System.runFinalizersOnExit(true); // Noncompliant
System.out.println("Program running with unsafe finalization.");
}
@Override
protected void finalize() {
System.out.println("Unpredictably finalizing objects.");
// Risky finalization logic
}
}
Example 3:
Positive
The positive example again shows how to use a shutdown hook for safely closing resources upon JVM shutdown, instead of relying on finalization.
public class SafeShutdownHook {
public static void main(String[] args) {
Thread resourceThread = new Thread(() -> closeOpenResources());
Runtime.getRuntime().addShutdownHook(resourceThread);
System.out.println("Application performing tasks...");
}
private static void closeOpenResources() {
System.out.println("Closing open resources safely.");
// Logic to close resources
}
}