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) { |