1 /*
   2  * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package sun.rmi.transport;
  26 
  27 import java.lang.ref.*;
  28 import sun.rmi.runtime.Log;
  29 
  30 /**
  31  * WeakRef objects are used by the RMI runtime to hold potentially weak
  32  * references to exported remote objects in the local object table.
  33  *
  34  * This class extends the functionality of java.lang.ref.WeakReference in
  35  * several ways.  The methods pin() and unpin() can be used to set
  36  * whether the contained reference is strong or weak (it is weak upon
  37  * construction).  The hashCode() and equals() methods are overridden so
  38  * that WeakRef objects hash and compare to each other according to the
  39  * object identity of their referents.
  40  *
  41  * @author  Ann Wollrath
  42  * @author  Peter Jones
  43  */
  44 class WeakRef extends WeakReference<Object> {
  45 
  46     /** value of the referent's "identity" hash code */
  47     private int hashValue;
  48 
  49     /** strong reference to the referent, for when this WeakRef is "pinned" */
  50     private Object strongRef = null;
  51 
  52     /**
  53      * Create a new WeakRef to the given object.
  54      */
  55     public WeakRef(Object obj) {
  56         super(obj);
  57         setHashValue(obj);      // cache object's "identity" hash code
  58     }
  59 
  60     /**
  61      * Create a new WeakRef to the given object, registered with a queue.
  62      */
  63     public WeakRef(Object obj, ReferenceQueue<Object> q) {
  64         super(obj, q);
  65         setHashValue(obj);      // cache object's "identity" hash code
  66     }
  67 
  68     /**
  69      * Pin the contained reference (make this a strong reference).
  70      */
  71     public synchronized void pin() {
  72         if (strongRef == null) {
  73             strongRef = get();
  74 
  75             if (DGCImpl.dgcLog.isLoggable(Log.VERBOSE)) {
  76                 DGCImpl.dgcLog.log(Log.VERBOSE,
  77                                    "strongRef = " + strongRef);
  78             }
  79         }
  80     }
  81 
  82     /**
  83      * Unpin the contained reference (make this a weak reference).
  84      */
  85     public synchronized void unpin() {
  86         if (strongRef != null) {
  87             if (DGCImpl.dgcLog.isLoggable(Log.VERBOSE)) {
  88                 DGCImpl.dgcLog.log(Log.VERBOSE,
  89                                    "strongRef = " + strongRef);
  90             }
  91 
  92             strongRef = null;
  93         }
  94     }
  95 
  96     /*
  97      * Cache referent's "identity" hash code (so that we still have the
  98      * value after the referent gets cleared).
  99      *
 100      * We cannot use the value from the object's hashCode() method, since
 101      * if the object is of a remote class not extended from RemoteObject
 102      * and it is trying to implement hashCode() and equals() so that it
 103      * can be compared to stub objects, its own hash code could not have
 104      * been initialized yet (see bugid 4102938).  Also, object table keys
 105      * based on server objects are indeed matched on object identity, so
 106      * this is the correct hash technique regardless.
 107      */
 108     private void setHashValue(Object obj) {
 109         if (obj != null) {
 110             hashValue = System.identityHashCode(obj);
 111         } else {
 112             hashValue = 0;
 113         }
 114     }
 115 
 116     /**
 117      * Always return the "identity" hash code of the original referent.
 118      */
 119     public int hashCode() {
 120         return hashValue;
 121     }
 122 
 123     /**
 124      * Return true if "obj" is this identical WeakRef object, or, if the
 125      * contained reference has not been cleared, if "obj" is another WeakRef
 126      * object with the identical non-null referent.  Otherwise, return false.
 127      */
 128     public boolean equals(Object obj) {
 129         if (obj instanceof WeakRef) {
 130             if (obj == this)
 131                 return true;
 132 
 133             Object referent = get();
 134             return (referent != null) && (referent == ((WeakRef) obj).get());
 135         } else {
 136             return false;
 137         }
 138     }
 139 }