All Downloads are FREE. Search and download functionalities are using the official Maven repository.

errorprone.bugpattern.UnsafeFinalization.md Maven / Gradle / Ivy

The newest version!
When invoking `static native` methods from objects that override
[`finalize`](https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#finalize--),
the finalizer may run before the native method finishes execution.

Consider the following example:

```java
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(nativeResourcePtr); // 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`](https://docs.oracle.com/javase/9/docs/api/java/lang/ref/Reference.html#reachabilityFence-java.lang.Object-)
will keep the reference passed in live. Be sure to call it in a finally block:

```java
 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

*   [Boehm, "Destructors, finalizers, and synchronization." POPL 2003.](http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html)
    Section 3.4 discusses this problem.
*   [Java Language Specification 12.6.2, "Interaction with the Memory Model."](https://docs.oracle.com/javase/specs/jls/se9/html/jls-12.html#jls-12.6.2)




© 2015 - 2025 Weber Informatics LLC | Privacy Policy