UnsafeFinalization
Finalizer may run before native code finishes execution

Category
Severity
WARNING
Maturity

The problem

When invoking static native methods from objects that override finalize, the finalizer may run before the native method finishes execution.

Consider the following example:

public class GameRunner {
  // Pointer to some native resource, stored as a long
  private long nativeResourcePtr;

  // Allocates the native resource that this object "owns"
  private static native long doNativeInit();

  // Releases the native resource
  private static native void cleanUpNativeResources(long nativeResourcePtr);

  public GameRunner() {
    nativeResourcePtr = doNativeInit();
  }

  @Override
  protected void finalize() {
    cleanUpNativeResources(nativeResourcePtr);
    nativeResourcePtr = 0;
    super.finalize();
  }

  public void run() {
    GameLibrary.playGame(nativeResourcePointer); // Bug!
  }
}

public class GameLibrary {
  // Plays the game using the native resource
  public static native void playGame(long nativeResourcePtr);
}

During the execution of GameRunner.run, the call to playGame may not hold the this reference live, and its finalizer may run, cleaning up the native resources while the native code is still executing.

You can fix this by making the static native method not static, or by changing the static native method so that it is passed the enclosing instance and not the nativeResourcePtr value directly.

If you can use Java 9, the new method Reference.reachabilityFence will keep the reference passed in live. Be sure to call it in a finally block:

 public void run() {
    try {
      playAwesomeGame(nativeResourcePtr);
    } finally {
      Reference.reachabilityFence(this);
    }
  }
}

Note: This check doesn’t currently detect this problem when passing fields from objects other than “this”. That is equally unsafe. Consider passing the Java object instead.

References

Suppression

Suppress false positives by adding the suppression annotation @SuppressWarnings("UnsafeFinalization") to the enclosing element.