Is it possible for the GC to manage its own resource object?

With the experience of C ++ and C # and some small knowledge of Java, I am starting a Java + JNI (C ++) project (if that matters).

I have my own method that creates some C ++ class and returns a pointer to it as a long Java value (say, a handle). And then other native methods, called Java code here and there, use the handle as a parameter to perform some of its own operations on this class. The C ++ side does not belong to this object, it is the Java side that does this. But in the current architecture design, it is difficult to determine exactly who owns the object and when to delete it. Therefore, it would be nice to make a Java VM garbage collector to somehow control the lifetime of the object. The C ++ class does not consume any resources, except for some part of the memory, not large. So everything is in order if several such objects are not destroyed.

In C #, I would probably wrap my own IntPtr handle in some class of managed wrappers. And redefine its finalizer to call the object's own destructor when the managed wrapper collects garbage. SafeHandle, AddMemoryPressure, etc. May also help here.

This is another story with Java ending. The second thing you know after "Hello world" in Java is that using finalize is bad. Are there any other ways to do this in Java? Perhaps using a PhantomReference?

+5
source share
4 answers

Well, consider the reason why WHY finalize and Co are problematic: as you know, there is no guarantee that finalization will be called before the VM is closed, which means that a special cleanup code will not necessarily be launched (imo a bad solution, I I don’t see any problems to start the finalization queue when cleaning, but it’s good that it is). Also this is exactly the same situation in C #

Now your objects only consume memory, which will be cleaned up by the OS anyway when the VM is destroyed, so the only case where finalization is problematic will not matter to you. So yes, you can really use this option, and it will work fine, but it cannot be considered a great architectural project - and as soon as you add resources to your C ++ code, where the OS will not correctly handle cleaning, you will encounter with problems

Also note that the implementation of the finalizer leads to some additional overhead for the GC and means that cleaning up one of these objects requires two cycles (and whatever you do, never save the object in the finalize method)

+5
source

If you understand why you should avoid using the Java completion method, you will also understand how to use it correctly. Using finalization to close system resources (files and descriptors) is bad, because you actually don't know when these resources will be closed and released. Using complex termination logic is bad, because a reference to an object may leak out and be pinned in memory again.

Great for finalizing your script.

+2
source

using a wrapper with a finalizer is a decent solution here

but if you really don't want to do this, you can use the PhantomReference with ReferenceQueue to clear it (but you will need a separate thread to poll the queue)

+1
source

So how can we achieve this using the phantom link.

  • Create a wrapper for your own intPtr object. Create a phantom link (with a reference queue) on the wrapper object.
  • Create and save the phantom reference map to intPtr.
  • Create a thread that will control the link queue for the final wrapper.
  • This thread will get the phantom link from the link queue, look for intPtr using the phantom link, and call the destructor in the int int object referenced by intPtr.
  • As long as all this happens, you can happily use wrappers in your Java code.
0
source

Source: https://habr.com/ru/post/892889/


All Articles