title: Gracefully finalizing the SoftReference referent
body: <p>I am using a search library which advises keeping search handle object open for this can benefit query cache. Over the time I have observed that the cache tends to get bloated (few hundred megs and keeps growing) and OOMs started to kick in. There is no way to enforce limits of this cache nor plan how much memory it can use. So I have increased the <em>Xmx</em> limit, but that's only a temporary solution to the problem.</p>
  
  <p>Eventually I am thinking to make this object a <em>referent</em> of <code>java.lang.ref.SoftReference</code>. So if the system runs low on free memory, it would let the object go and a new one would be created on demand. This would decrease some speed after fresh start, but this is a much better alternative than hitting OOM.</p>
  
  <p>The only problem I see about SoftReferences is that there is no clean way of getting their referents finalized. In my case, before destroying the search handle I need to close it, otherwise the system might run out of file descriptors. Obviously, I can wrap this handle into another object, write a finalizer on it (or hook onto a ReferenceQueue/PhantomReference) and let go. But hey, every single article in this planet advises against using finalizers, and especially - against finalizers for freeing file handles (e.g. <em>Effective Java</em> ed. II, page 27.).</p>
  
  <p>So I am somewhat puzzled. Should I carefully ignore all these advices and go on. Otherwise, are there any other viable alternatives? Thanks in advance.</p>
  
  <p>EDIT #1: Text below was added after testing some code as suggested by Tom Hawtin. To me, it appears that either suggestion isn't working or I am missing something. Here's the code:</p>
  
  <pre><code>class Bloat {  // just a heap filler really
     private double a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;
  
     private final int ii;
  
     public Bloat(final int ii) {
        this.ii = ii;
     }
  }
  
  // as recommended by Tom Hawtin
  class MyReference&lt;T&gt; extends SoftReference&lt;T&gt; {
     private final T hardRef;
  
     MyReference(T referent, ReferenceQueue&lt;? super T&gt; q) {
        super(referent, q);
        this.hardRef = referent;
     }
  }
  
  //...meanwhile, somewhere in the neighbouring galaxy...
  {
     ReferenceQueue&lt;Bloat&gt; rq = new ReferenceQueue&lt;Bloat&gt;();
     Set&lt;SoftReference&lt;Bloat&gt;&gt; set = new HashSet&lt;SoftReference&lt;Bloat&gt;&gt;();
     int i=0;
  
     while(i&lt;50000) {
  //      set.add(new MyReference&lt;Bloat&gt;(new Bloat(i), rq));
        set.add(new SoftReference&lt;Bloat&gt;(new Bloat(i), rq));
  
  //      MyReference&lt;Bloat&gt; polled = (MyReference&lt;Bloat&gt;) rq.poll();
        SoftReference&lt;Bloat&gt; polled = (SoftReference&lt;Bloat&gt;) rq.poll();
  
        if (polled != null) {
           Bloat polledBloat = polled.get();
           if (polledBloat == null) {
             System.out.println("is null :(");
           } else {
             System.out.println("is not null!");
           }
        }
        i++;
     }
  }
  </code></pre>
  
  <p>If I run the snippet above with <code>-Xmx10m</code> and SoftReferences (as in code above), I'm getting tons of <code>is null :(</code> printed. But if I replace the code with <code>MyReference</code> (uncommenting two lines with MyReference and commenting out ones with SoftReference) I always get OOM. </p>
  
  <p>As I understood from the advice, having hard reference inside <code>MyReference</code> should not prevent object hitting <code>ReferenceQueue</code>, right?</p>