src/share/classes/sun/rmi/transport/Target.java

Print this page




  36 import sun.rmi.runtime.NewThreadAction;
  37 import sun.rmi.server.Dispatcher;
  38 
  39 /**
  40  * A target contains information pertaining to a remote object that
  41  * resides in this address space.  Targets are located via the
  42  * ObjectTable.
  43  */
  44 public final class Target {
  45     /** object id for target */
  46     private final ObjID id;
  47     /** flag indicating whether target is subject to collection */
  48     private final boolean permanent;
  49     /** weak reference to remote object implementation */
  50     private final WeakRef weakImpl;
  51     /** dispatcher for remote object */
  52     private volatile Dispatcher disp;
  53     /** stub for remote object */
  54     private final Remote stub;
  55     /** set of clients that hold references to this target */
  56     private final Vector refSet = new Vector();
  57     /** table that maps client endpoints to sequence numbers */
  58     private final Hashtable sequenceTable = new Hashtable(5);

  59     /** access control context in which target was created */
  60     private final AccessControlContext acc;
  61     /** context class loader in which target was created */
  62     private final ClassLoader ccl;
  63     /** number of pending/executing calls */
  64     private int callCount = 0;
  65     /** true if this target has been removed from the object table */
  66     private boolean removed = false;
  67     /**
  68      * the transport through which this target was exported and
  69      * through which remote calls will be allowed
  70      */
  71     private volatile Transport exportedTransport = null;
  72 
  73     /** number to identify next callback thread created here */
  74     private static int nextThreadNum = 0;
  75 
  76     /**
  77      * Construct a Target for a remote object "impl" with
  78      * a specific object id.


 224         }
 225     }
 226 
 227     /**
 228      * Enable the transport through which remote calls to this target
 229      * are allowed to be set if it has not already been set.
 230      */
 231     void setExportedTransport(Transport exportedTransport) {
 232         if (this.exportedTransport == null) {
 233             this.exportedTransport = exportedTransport;
 234         }
 235     }
 236 
 237     /**
 238      * Add an endpoint to the remembered set.  Also adds a notifier
 239      * to call back if the address space associated with the endpoint
 240      * dies.
 241      */
 242     synchronized void referenced(long sequenceNum, VMID vmid) {
 243         // check sequence number for vmid
 244         SequenceEntry entry = (SequenceEntry) sequenceTable.get(vmid);
 245         if (entry == null) {
 246             sequenceTable.put(vmid, new SequenceEntry(sequenceNum));
 247         } else if (entry.sequenceNum < sequenceNum) {
 248             entry.update(sequenceNum);
 249         } else  {
 250             // late dirty call; ignore.
 251             return;
 252         }
 253 
 254         if (!refSet.contains(vmid)) {
 255             /*
 256              * A Target must be pinned while its refSet is not empty.  It may
 257              * have become unpinned if external LiveRefs only existed in
 258              * serialized form for some period of time, or if a client failed
 259              * to renew its lease due to a transient network failure.  So,
 260              * make sure that it is pinned here; this fixes bugid 4069644.
 261              */
 262             pinImpl();
 263             if (getImpl() == null)      // too late if impl was collected
 264                 return;
 265 
 266             if (DGCImpl.dgcLog.isLoggable(Log.VERBOSE)) {
 267                 DGCImpl.dgcLog.log(Log.VERBOSE, "add to dirty set: " + vmid);
 268             }
 269 
 270             refSet.addElement(vmid);
 271 
 272             DGCImpl.getDGCImpl().registerTarget(vmid, this);
 273         }
 274     }
 275 
 276     /**
 277      * Remove endpoint from remembered set.  If set becomes empty,
 278      * remove server from Transport's object table.
 279      */
 280     synchronized void unreferenced(long sequenceNum, VMID vmid, boolean strong)
 281     {
 282         // check sequence number for vmid
 283         SequenceEntry entry = (SequenceEntry) sequenceTable.get(vmid);
 284         if (entry == null || entry.sequenceNum > sequenceNum) {
 285             // late clean call; ignore
 286             return;
 287         } else if (strong) {
 288             // strong clean call; retain sequenceNum
 289             entry.retain(sequenceNum);
 290         } else if (entry.keep == false) {
 291             // get rid of sequence number
 292             sequenceTable.remove(vmid);
 293         }
 294 
 295         if (DGCImpl.dgcLog.isLoggable(Log.VERBOSE)) {
 296             DGCImpl.dgcLog.log(Log.VERBOSE, "remove from dirty set: " + vmid);
 297         }
 298 
 299         refSetRemove(vmid);
 300     }
 301 
 302     /**
 303      * Remove endpoint from the reference set.


 349     }
 350 
 351     /**
 352      * Mark this target as not accepting new calls if any of the
 353      * following conditions exist: a) the force parameter is true,
 354      * b) the target's call count is zero, or c) the object is already
 355      * not accepting calls. Returns true if target is marked as not
 356      * accepting new calls; returns false otherwise.
 357      */
 358     synchronized boolean unexport(boolean force) {
 359 
 360         if ((force == true) || (callCount == 0) || (disp == null)) {
 361             disp = null;
 362             /*
 363              * Fix for 4331349: unpin object so that it may be gc'd.
 364              * Also, unregister all vmids referencing this target
 365              * so target can be gc'd.
 366              */
 367             unpinImpl();
 368             DGCImpl dgc = DGCImpl.getDGCImpl();
 369             Enumeration enum_ = refSet.elements();
 370             while (enum_.hasMoreElements()) {
 371                 VMID vmid = (VMID) enum_.nextElement();
 372                 dgc.unregisterTarget(vmid, this);
 373             }
 374             return true;
 375         } else {
 376             return false;
 377         }
 378     }
 379 
 380     /**
 381      * Mark this target as having been removed from the object table.
 382      */
 383     synchronized void markRemoved() {
 384         if (!(!removed)) { throw new AssertionError(); }
 385 
 386         removed = true;
 387         if (!permanent && callCount == 0) {
 388             ObjectTable.decrementKeepAliveCount();
 389         }
 390 
 391         if (exportedTransport != null) {




  36 import sun.rmi.runtime.NewThreadAction;
  37 import sun.rmi.server.Dispatcher;
  38 
  39 /**
  40  * A target contains information pertaining to a remote object that
  41  * resides in this address space.  Targets are located via the
  42  * ObjectTable.
  43  */
  44 public final class Target {
  45     /** object id for target */
  46     private final ObjID id;
  47     /** flag indicating whether target is subject to collection */
  48     private final boolean permanent;
  49     /** weak reference to remote object implementation */
  50     private final WeakRef weakImpl;
  51     /** dispatcher for remote object */
  52     private volatile Dispatcher disp;
  53     /** stub for remote object */
  54     private final Remote stub;
  55     /** set of clients that hold references to this target */
  56     private final Vector<VMID> refSet = new Vector<>();
  57     /** table that maps client endpoints to sequence numbers */
  58     private final Hashtable<VMID, SequenceEntry> sequenceTable =
  59         new Hashtable<>(5);
  60     /** access control context in which target was created */
  61     private final AccessControlContext acc;
  62     /** context class loader in which target was created */
  63     private final ClassLoader ccl;
  64     /** number of pending/executing calls */
  65     private int callCount = 0;
  66     /** true if this target has been removed from the object table */
  67     private boolean removed = false;
  68     /**
  69      * the transport through which this target was exported and
  70      * through which remote calls will be allowed
  71      */
  72     private volatile Transport exportedTransport = null;
  73 
  74     /** number to identify next callback thread created here */
  75     private static int nextThreadNum = 0;
  76 
  77     /**
  78      * Construct a Target for a remote object "impl" with
  79      * a specific object id.


 225         }
 226     }
 227 
 228     /**
 229      * Enable the transport through which remote calls to this target
 230      * are allowed to be set if it has not already been set.
 231      */
 232     void setExportedTransport(Transport exportedTransport) {
 233         if (this.exportedTransport == null) {
 234             this.exportedTransport = exportedTransport;
 235         }
 236     }
 237 
 238     /**
 239      * Add an endpoint to the remembered set.  Also adds a notifier
 240      * to call back if the address space associated with the endpoint
 241      * dies.
 242      */
 243     synchronized void referenced(long sequenceNum, VMID vmid) {
 244         // check sequence number for vmid
 245         SequenceEntry entry = sequenceTable.get(vmid);
 246         if (entry == null) {
 247             sequenceTable.put(vmid, new SequenceEntry(sequenceNum));
 248         } else if (entry.sequenceNum < sequenceNum) {
 249             entry.update(sequenceNum);
 250         } else  {
 251             // late dirty call; ignore.
 252             return;
 253         }
 254 
 255         if (!refSet.contains(vmid)) {
 256             /*
 257              * A Target must be pinned while its refSet is not empty.  It may
 258              * have become unpinned if external LiveRefs only existed in
 259              * serialized form for some period of time, or if a client failed
 260              * to renew its lease due to a transient network failure.  So,
 261              * make sure that it is pinned here; this fixes bugid 4069644.
 262              */
 263             pinImpl();
 264             if (getImpl() == null)      // too late if impl was collected
 265                 return;
 266 
 267             if (DGCImpl.dgcLog.isLoggable(Log.VERBOSE)) {
 268                 DGCImpl.dgcLog.log(Log.VERBOSE, "add to dirty set: " + vmid);
 269             }
 270 
 271             refSet.addElement(vmid);
 272 
 273             DGCImpl.getDGCImpl().registerTarget(vmid, this);
 274         }
 275     }
 276 
 277     /**
 278      * Remove endpoint from remembered set.  If set becomes empty,
 279      * remove server from Transport's object table.
 280      */
 281     synchronized void unreferenced(long sequenceNum, VMID vmid, boolean strong)
 282     {
 283         // check sequence number for vmid
 284         SequenceEntry entry = sequenceTable.get(vmid);
 285         if (entry == null || entry.sequenceNum > sequenceNum) {
 286             // late clean call; ignore
 287             return;
 288         } else if (strong) {
 289             // strong clean call; retain sequenceNum
 290             entry.retain(sequenceNum);
 291         } else if (entry.keep == false) {
 292             // get rid of sequence number
 293             sequenceTable.remove(vmid);
 294         }
 295 
 296         if (DGCImpl.dgcLog.isLoggable(Log.VERBOSE)) {
 297             DGCImpl.dgcLog.log(Log.VERBOSE, "remove from dirty set: " + vmid);
 298         }
 299 
 300         refSetRemove(vmid);
 301     }
 302 
 303     /**
 304      * Remove endpoint from the reference set.


 350     }
 351 
 352     /**
 353      * Mark this target as not accepting new calls if any of the
 354      * following conditions exist: a) the force parameter is true,
 355      * b) the target's call count is zero, or c) the object is already
 356      * not accepting calls. Returns true if target is marked as not
 357      * accepting new calls; returns false otherwise.
 358      */
 359     synchronized boolean unexport(boolean force) {
 360 
 361         if ((force == true) || (callCount == 0) || (disp == null)) {
 362             disp = null;
 363             /*
 364              * Fix for 4331349: unpin object so that it may be gc'd.
 365              * Also, unregister all vmids referencing this target
 366              * so target can be gc'd.
 367              */
 368             unpinImpl();
 369             DGCImpl dgc = DGCImpl.getDGCImpl();
 370             Enumeration<VMID> enum_ = refSet.elements();
 371             while (enum_.hasMoreElements()) {
 372                 VMID vmid = enum_.nextElement();
 373                 dgc.unregisterTarget(vmid, this);
 374             }
 375             return true;
 376         } else {
 377             return false;
 378         }
 379     }
 380 
 381     /**
 382      * Mark this target as having been removed from the object table.
 383      */
 384     synchronized void markRemoved() {
 385         if (!(!removed)) { throw new AssertionError(); }
 386 
 387         removed = true;
 388         if (!permanent && callCount == 0) {
 389             ObjectTable.decrementKeepAliveCount();
 390         }
 391 
 392         if (exportedTransport != null) {