Have you ever used PhantomReference in any project?

后端 未结 9 438
再見小時候
再見小時候 2020-11-29 17:02

The only thing I know about PhantomReference is,

  • If you use its get() method, it will always return null
相关标签:
9条回答
  • 2020-11-29 18:02

    THIS SHOULD BE OBSOLETE WITH JAVA 9!
    Use java.util.Cleaner instead! (Or sun.misc.Cleaner on older JRE)

    Original post:


    I found that the use of PhantomReferences has nearly the same amount of pitfalls as finalizer methods (but a fewer problems once you get it right). I have written a small solution (a very small framework to use PhantomReferences) for Java 8. It allows to use lambda expressions as callbacks to be run after the object has been removed. You can register the callbacks for inner resources that should be closed. With this I have found a solution that works for me as it makes it much more practical.

    https://github.com/claudemartin/java-cleanup

    Here's a small example to show how a callback is registered:

      class Foo implements Cleanup {
        //...  
        public Foo() { 
        //...    
          this.registerCleanup((value) -> {
            try {
              // 'value' is 'this.resource'
              value.close();
            } catch (Exception e) {
              logger.warning("closing resource failed", e);
            }
          }, this.resource);
        }
    

    And then there is the even simpler method for auto-close, doing about the same as the above:

    this.registerAutoClose(this.resource);
    

    To answer your questions:

    [ then whats the use of it ]

    You can't clean up something that doesn't exist. But it could have had resources that still exist and need to be cleaned up so they can be removed.

    But what is the use of this concept/class?

    It's not necessarily to do anything with any effect other than debugging/logging. Or maybe for statistics. I see it more like a notification service from the GC. You could also want to use it to remove aggregated data that becomes irrelevant once the object is removed (but there are probably better solutions for that). Examples often mention database connections to be closed, but I don't see how this is such a good idea as you couldn't work with transactions. An application framework will provide a much better solution for that.

    Have you ever used this in any of your project, or do you have any example where we should use this? Or is this concept made just for interview point of view ;)

    I use it mostly just for logging. So I can trace the removed elements and see how GC works and can be tweaked. I wouldn't run any critical code in this way. If something needs to be closed then it should be done in a try-with-resource-statement. And I use it in unit tests, to make sure I don't have any memory leaks. The same way as jontejj does it. But my solution is a bit more general.

    0 讨论(0)
  • 2020-11-29 18:04

    It is common to use WeakReference where PhantomReference is more appropriate. This avoids certain problems of being able to resurrect objects after a WeakReference is cleared/enqueued by the garbage collector. Usually the difference doesn't matter because people are not playing silly buggers.

    Using PhantomReference tends to be a bit more intrusive because you can't pretend that the get method works. You can't, for example, write a Phantom[Identity]HashMap.

    0 讨论(0)
  • 2020-11-29 18:07

    I used PhantomReferences in a simplistic, very specialized kind of memory profiler to monitor object creation and destruction. I needed them to keep track of destruction. But the approach is out-dated. (It was written in 2004 targeting J2SE 1.4.) Professional profiling tools are much more powerful and reliable and the newer Java 5 features like JMX or agents and JVMTI can be used for that too.

    PhantomReferences (always used together with the Reference queue) are superior to finalize which has some problems and should therefore be avoided. Mainly making objects reachable again. This could be avoided with the finalizer guardian idiom (-> read more in 'Effective Java'). So they are also the new finalize.

    Furthermore, PhantomReferences

    allow you to determine exactly when an object was removed from memory. They are in fact the only way to determine that. This isn't generally that useful, but might come in handy in certain very specific circumstances like manipulating large images: if you know for sure that an image should be garbage collected, you can wait until it actually is before attempting to load the next image, and therefore make the dreaded OutOfMemoryError less likely. (Quoted from enicholas.)

    And as psd wrote first, Roedy Green has a good summary of references.

    0 讨论(0)
提交回复
热议问题