In Java the memory allocated by NIO direct buffers is freed with sun.misc.Cleaner
instances, some special phantom references that are more efficient than object fin
Hope it help you if using java9.
The code below was already tested in Intellij IDEA 2017 and oracle jdk 9.
import java.lang.ref.Cleaner;
public class Main {
public Main() {
}
public static void main(String[] args) {
System.out.println("Hello World!");
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Cleaner cleaner = Cleaner.create();
Main obj = new Main();
cleaner.register(obj, new Runnable() {
@Override
public void run() {
System.out.println("Hello World!222");
}
});
System.gc();
}
}
}
If you rely on anything in a sun.misc
package, you run the risk of it disappearing and breaking your code. Some pieces are more stable than others, but it's often a bad idea (devil's advocate: a lot of the methods in sun.misc.Unsafe
are actually implemented by JVM intrinsics, making them faster than user-written JNI code).
In this case, I think it's a bad idea: Cleaner
is one possible implementation of cleanup via PhantomReference
. There are others; Google for examples. For that matter, you could look at the source code of Cleaner
itself as an example of how to use phantom references.
You will need some sort of cleanup handler if you're going to have on-heap objects that refer to off-heap objects. Otherwise you'll create a true memory leak when those on-heap objects get collected.
After spending more time reading the API doc ( http://docs.oracle.com/javase/7/docs/api/java/lang/ref/package-summary.html ) I think I have a more detailed answer:
1) it is possible to reuse sun.misc.Cleaner to perform the efficient cleanup of your own custom classes. You declare the cleaner by calling the provided factory method:
sun.misc.Cleaner.create(Object ob, Runnable cleanup);
For some time I could not get it to work properly, that's because I was moronic enough to define the runnable cleanup code of my cleaner as an anonymous class, that kept a (strong) reference to my referent object, preventing it from ever being "phantom reachable"...
2) There is no other way to implement such efficient cleanup (not even with the help of phantom references)
Indeed the reference handler thread handles instances of sun.misc.Cleaner in a special way:
// Fast path for cleaners
if (r instanceof Cleaner) {
((Cleaner)r).clean();
continue;
}
That means that the cleanup code is called directly from the reference handler thread, while in standard usage, the references must be enqueued by the reference handler thread and then dequeued and processed by another application thread.