//TCPTransport#exportObject publicvoidexportObject(Target target)throws RemoteException { /* * Ensure that a server socket is listening, and count this * export while synchronized to prevent the server socket from * being closed due to concurrent unexports. */ synchronized (this) { listen(); exportCount++; }
/* * Try to add the Target to the exported object table; keep * counting this export (to keep server socket open) only if * that succeeds. */ booleanok=false; try { super.exportObject(target); ok = true; } finally { if (!ok) { synchronized (this) { decrementExportCount(); } } } }
if (server == null) { if (tcpLog.isLoggable(Log.BRIEF)) { tcpLog.log(Log.BRIEF, "(port " + port + ") create server socket"); }
try { server = ep.newServerSocket(); /* * Don't retry ServerSocket if creation fails since * "port in use" will cause export to hang if an * RMIFailureHandler is not installed. */ Threadt= AccessController.doPrivileged( newNewThreadAction(newAcceptLoop(server), "TCP Accept-" + port, true)); t.start(); } catch (java.net.BindException e) { thrownewExportException("Port already in use: " + port, e); } catch (IOException e) { thrownewExportException("Listen failed on port: " + port, e); }
} else { // otherwise verify security access to existing server socket SecurityManagersm= System.getSecurityManager(); if (sm != null) { sm.checkListen(port); } } }
在构造socket的过程中,如果说端口是0的话,就会随机设置一个端口
1 2
if (listenPort == 0) setDefaultPort(server.getLocalPort(), csf, ssf);
privatevoidsetup(UnicastServerRef uref) throws RemoteException { /* Server ref must be created and assigned before remote * object 'this' can be exported. */ ref = uref; uref.exportObject(this, null, true); }
// UnicastRemoteObject#exportObject privatestatic Remote exportObject(Remote obj, UnicastServerRef sref) throws RemoteException { // if obj extends UnicastRemoteObject, set its ref. if (obj instanceof UnicastRemoteObject) { ((UnicastRemoteObject) obj).ref = sref; } return sref.exportObject(obj, null, false); }
/* Make sure to use the local stub loader for the stub classes. * When loaded by the local loader the load path can be * propagated to remote clients, by the MarshalOutputStream/InStream * pickle methods */ try { Class<?> stubcl = Class.forName(stubname, false, remoteClass.getClassLoader()); Constructor<?> cons = stubcl.getConstructor(stubConsParamTypes); return (RemoteStub) cons.newInstance(newObject[] { ref });
} catch (ClassNotFoundException e) { thrownewStubNotFoundException( "Stub class not found: " + stubname, e); } catch (NoSuchMethodException e) { thrownewStubNotFoundException( "Stub class missing constructor: " + stubname, e); } catch (InstantiationException e) { thrownewStubNotFoundException( "Can't create instance of stub class: " + stubname, e); } catch (IllegalAccessException e) { thrownewStubNotFoundException( "Stub class constructor not public: " + stubname, e); } catch (InvocationTargetException e) { thrownewStubNotFoundException( "Exception creating instance of stub class: " + stubname, e); } catch (ClassCastException e) { thrownewStubNotFoundException( "Stub class not instance of RemoteStub: " + stubname, e); } }
publicvoidsetSkeleton(Remote impl)throws RemoteException { if (!withoutSkeletons.containsKey(impl.getClass())) { try { skel = Util.createSkeleton(impl); } catch (SkeletonNotFoundException e) { /* * Ignore exception for skeleton class not found, because a * skeleton class is not necessary with the 1.2 stub protocol. * Remember that this impl's class does not have a skeleton * class so we don't waste time searching for it again. */ withoutSkeletons.put(impl.getClass(), null); } } }
static Skeleton createSkeleton(Remote object) throws SkeletonNotFoundException { Class<?> cl; try { cl = getRemoteClass(object.getClass()); } catch (ClassNotFoundException ex ) { thrownewSkeletonNotFoundException( "object does not implement a remote interface: " + object.getClass().getName()); }
// now try to load the skeleton based ont he name of the class Stringskelname= cl.getName() + "_Skel"; try { Class<?> skelcl = Class.forName(skelname, false, cl.getClassLoader());
if (host == null || host.length() == 0) { // If host is blank (as returned by "file:" URL in 1.0.2 used in // java.rmi.Naming), try to convert to real local host name so // that the RegistryImpl's checkAccess will not fail. try { host = java.net.InetAddress.getLocalHost().getHostAddress(); } catch (Exception e) { // If that failed, at least try "" (localhost) anyway... host = ""; } } LiveRefliveRef= newLiveRef(newObjID(ObjID.REGISTRY_ID), newTCPEndpoint(host, port, csf, null), false); RemoteRefref= (csf == null) ? newUnicastRef(liveRef) : newUnicastRef2(liveRef);
// read return value switch (returnType) { case TransportConstants.NormalReturn: break;
case TransportConstants.ExceptionalReturn: Object ex; try { ex = in.readObject(); } catch (Exception e) { thrownewUnmarshalException("Error unmarshaling return", e); }
// An exception should have been received, // if so throw it, else flag error if (ex instanceof Exception) { exceptionReceivedFromServer((Exception) ex); } else { thrownewUnmarshalException("Return type not Exception"); } // Exception is thrown before fallthrough can occur default: if (Transport.transportLog.isLoggable(Log.BRIEF)) { Transport.transportLog.log(Log.BRIEF, "return code invalid: " + returnType); } thrownewUnmarshalException("Return code invalid"); } }
/* StreamRemoteCall.done() does not actually make use * of conn, therefore it is safe to reuse this * connection before the dirty call is sent for * registered refs. */ ObjectreturnValue= unmarshalValue(rtype, in);
/* we are freeing the connection now, do not free * again or reuse. */ alreadyFreed = true;
/* if we got to this point, reuse must have been true. */ clientRefLog.log(Log.BRIEF, "free connection (reuse = true)");
/* Free the call's connection early. */ ref.getChannel().free(conn, true);
thrownewUnmarshalException("error unmarshalling return", e); } finally { try { call.done(); } catch (IOException e) { /* WARNING: If the conn has been reused early, * then it is too late to recover from thrown * IOExceptions caught here. This code is relying * on StreamRemoteCall.done() not actually * throwing IOExceptions. */ reuse = false; } }
} catch (RuntimeException e) { /* * Need to distinguish between client (generated by the * invoke method itself) and server RuntimeExceptions. * Client side RuntimeExceptions are likely to have * corrupted the call connection and those from the server * are not likely to have done so. If the exception came * from the server the call connection should be reused. */ if ((call == null) || (((StreamRemoteCall) call).getServerException() != e)) { reuse = false; } throw e;
} catch (RemoteException e) { /* * Some failure during call; assume connection cannot * be reused. Must assume failure even if ServerException * or ServerError occurs since these failures can happen * during parameter deserialization which would leave * the connection in a corrupted state. */ reuse = false; throw e;
} catch (Error e) { /* If errors occurred, the connection is most likely not * reusable. */ reuse = false; throw e;
} finally {
/* alreadyFreed ensures that we do not log a reuse that * may have already happened. */ if (!alreadyFreed) { if (clientRefLog.isLoggable(Log.BRIEF)) { clientRefLog.log(Log.BRIEF, "free connection (reuse = " + reuse + ")"); } ref.getChannel().free(conn, reuse); } } }
if (server == null) { if (tcpLog.isLoggable(Log.BRIEF)) { tcpLog.log(Log.BRIEF, "(port " + port + ") create server socket"); }
try { server = ep.newServerSocket(); /* * Don't retry ServerSocket if creation fails since * "port in use" will cause export to hang if an * RMIFailureHandler is not installed. */ Threadt= AccessController.doPrivileged( newNewThreadAction(newAcceptLoop(server), "TCP Accept-" + port, true)); t.start(); } catch (java.net.BindException e) { thrownewExportException("Port already in use: " + port, e); } catch (IOException e) { thrownewExportException("Listen failed on port: " + port, e); } ...... }
publicvoidrun() { try { executeAcceptLoop(); } finally { try { /* * Only one accept loop is started per server * socket, so after no more connections will be * accepted, ensure that the server socket is no * longer listening. */ serverSocket.close(); } catch (IOException e) { } } }
try { DataInputStreamin=newDataInputStream(conn.getInputStream()); do { intop= in.read(); // transport op if (op == -1) { if (tcpLog.isLoggable(Log.BRIEF)) { tcpLog.log(Log.BRIEF, "(port " + port + ") connection closed"); } break; }
if (tcpLog.isLoggable(Log.BRIEF)) { tcpLog.log(Log.BRIEF, "(port " + port + ") op = " + op); }
switch (op) { case TransportConstants.Call: // service incoming RMI call RemoteCallcall=newStreamRemoteCall(conn); if (serviceCall(call) == false) return; break;
case TransportConstants.Ping: ...... } } while (persistent);
publicvoiddispatch(Remote obj, RemoteCall call)throws IOException { // positive operation number in 1.1 stubs; // negative version number in 1.2 stubs and beyond... int num; long op;
try { // read remote call header ObjectInput in; try { in = call.getInputStream(); num = in.readInt(); if (num >= 0) { if (skel != null) { oldDispatch(obj, call, num); return; } else { thrownewUnmarshalException( "skeleton class not found but required " + "for client version"); } } op = in.readLong(); } catch (Exception readEx) { thrownewUnmarshalException("error unmarshalling call header", readEx); }
// make upcall on remote object Object result; try { result = method.invoke(obj, params); } catch (InvocationTargetException e) { throw e.getTargetException(); }
// marshal return value try { ObjectOutputout= call.getResultStream(true); Class<?> rtype = method.getReturnType(); if (rtype != void.class) { marshalValue(rtype, result, out); } } catch (IOException ex) { thrownewMarshalException("error marshalling return", ex); /* * This throw is problematic because when it is caught below, * we attempt to marshal it back to the client, but at this * point, a "normal return" has already been indicated, * so marshalling an exception will corrupt the stream. * This was the case with skeletons as well; there is no * immediately obvious solution without a protocol change. */ } } catch (Throwable e) { logCallException(e);
ObjectOutputout= call.getResultStream(false); if (e instanceof Error) { e = newServerError( "Error occurred in server thread", (Error) e); } elseif (e instanceof RemoteException) { e = newServerException( "RemoteException occurred in server thread", (Exception) e); } if (suppressStackTraces) { clearStackTraces(e); } out.writeObject(e); } finally { call.releaseInputStream(); // in case skeleton doesn't call.releaseOutputStream(); } }
if (DGCImpl.dgcLog.isLoggable(Log.VERBOSE)) { DGCImpl.dgcLog.log(Log.VERBOSE, "add object " + oe); }
synchronized (tableLock) { /** * Do nothing if impl has already been collected (see 6597112). Check while * holding tableLock to ensure that Reaper cannot process weakImpl in between * null check and put/increment effects. */ if (target.getImpl() != null) { if (objTable.containsKey(oe)) { thrownewExportException( "internal error: ObjID already in use"); } elseif (implTable.containsKey(weakImpl)) { thrownewExportException("object already exported"); }
static { /* * "Export" the singleton DGCImpl in a context isolated from * the arbitrary current thread context. */ AccessController.doPrivileged(newPrivilegedAction<Void>() { public Void run() { ClassLoadersavedCcl= Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader( ClassLoader.getSystemClassLoader());
/* * Put remote collector object in table by hand to prevent * listen on port. (UnicastServerRef.exportObject would * cause transport to listen.) */ try { dgc = newDGCImpl(); ObjIDdgcID=newObjID(ObjID.DGC_ID); LiveRefref=newLiveRef(dgcID, 0); UnicastServerRefdisp=newUnicastServerRef(ref); Remotestub= Util.createProxy(DGCImpl.class, newUnicastRef(ref), true); disp.setSkeleton(dgc);
staticvoidregisterRefs(Endpoint ep, List<LiveRef> refs) { /* * Look up the given endpoint and register the refs with it. * The retrieved entry may get removed from the global endpoint * table before EndpointEntry.registerRefs() is able to acquire * its lock; in this event, it returns false, and we loop and * try again. */ EndpointEntry epEntry; do { epEntry = EndpointEntry.lookup(ep); } while (!epEntry.registerRefs(refs)); }
if (in instanceof ConnectionInputStream) { ConnectionInputStreamstream= (ConnectionInputStream)in; // save ref to send "dirty" call after all args/returns // have been unmarshaled. stream.saveRef(ref); if (isResultStream) { // set flag in stream indicating that remote objects were // unmarshaled. A DGC ack should be sent by the transport. stream.setAckNeeded(); } } else { DGCClient.registerRefs(ep, Arrays.asList(newLiveRef[] { ref })); }
if (in instanceof ConnectionInputStream) { ConnectionInputStreamstream= (ConnectionInputStream)in; // save ref to send "dirty" call after all args/returns // have been unmarshaled. stream.saveRef(ref); if (isResultStream) { // set flag in stream indicating that remote objects were // unmarshaled. A DGC ack should be sent by the transport. stream.setAckNeeded(); } } else { DGCClient.registerRefs(ep, Arrays.asList(newLiveRef[] { ref })); }
public Object get(Object key) { // create value for key if key is not currently in the map if (map.containsKey(key) == false) { Objectvalue= factory.transform(key); map.put(key, value); return value; } return map.get(key); } //构造函数 protectedLazyMap(Map map, Transformer factory) { super(map); if (factory == null) { thrownewIllegalArgumentException("Factory must not be null"); } this.factory = factory; }
public Object getValue() { return map.get(key); } //LazyMap public Object get(Object key) { // create value for key if key is not currently in the map if (map.containsKey(key) == false) { Objectvalue= factory.transform(key); map.put(key, value); return value; } return map.get(key); }
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { thrownewjava.io.StreamCorruptedException(); } }
publicbooleanoffer(E e) { if (e == null) thrownewNullPointerException(); modCount++; inti= size; if (i >= queue.length) grow(i + 1); size = i + 1; if (i == 0) queue[0] = e; else siftUp(i, e); returntrue; }
这里的grow方法其实无关紧要,if判断中的queue.length在默认情况下是11,grow方法的作用就是// Double size if small; else grow by 50%,就是如果i大于等于这个长度时,就会扩大这个队列的长度
publicintcompare(final I obj1, final I obj2) { finalOvalue1=this.transformer.transform(obj1); finalOvalue2=this.transformer.transform(obj2); returnthis.decorated.compare(value1, value2); }
publicintcompare(final I obj1, final I obj2) { finalOvalue1=this.transformer.transform(obj1); finalOvalue2=this.transformer.transform(obj2); returnthis.decorated.compare(value1, value2); }
publicTransformingComparator(final Transformer<? super I, ? extends O> transformer) { this(transformer, ComparatorUtils.NATURAL_COMPARATOR); }
publicTransformingComparator(final Transformer<? super I, ? extends O> transformer, final Comparator<O> decorated) { this.decorated = decorated; this.transformer = transformer; }
publicPriorityQueue(Comparator<? super E> comparator) { this(DEFAULT_INITIAL_CAPACITY, comparator); } publicPriorityQueue(int initialCapacity, Comparator<? super E> comparator) { // Note: This restriction of at least one is not actually needed, // but continues for 1.5 compatibility if (initialCapacity < 1) thrownewIllegalArgumentException(); this.queue = newObject[initialCapacity]; this.comparator = comparator; }
public Object transform(Object input) { try { if (input instanceof Class == false) { thrownewFunctorException( "InstantiateTransformer: Input object was not an instanceof Class, it was a " + (input == null ? "null object" : input.getClass().getName())); } Constructorcon= ((Class) input).getConstructor(iParamTypes); return con.newInstance(iArgs);
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { ...... if (c == null) { // If still not found, then invoke findClass in order // to find the class. longt1= System.nanoTime(); c = findClass(name);
// The translet needs to keep a reference to all its auxiliary // class to prevent the GC from collecting them AbstractTranslettranslet= (AbstractTranslet) _class[_transletIndex].newInstance(); translet.postInitialization(); translet.setTemplates(this); translet.setServicesMechnism(_useServicesMechanism); translet.setAllowedProtocols(_accessExternalStylesheet); if (_auxClasses != null) { translet.setAuxiliaryClasses(_auxClasses); }
// 动态调试跟到这里 public Object get(Object key) { // create value for key if key is not currently in the map if (map.containsKey(key) == false) { Objectvalue= factory.transform(key); map.put(key, value); return value; } return map.get(key); }