Merge Orp RMI patches from Wu Gansha <gansha.wu@intel.com>
authormark <mark@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Nov 2002 18:01:05 +0000 (18:01 +0000)
committermark <mark@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Nov 2002 18:01:05 +0000 (18:01 +0000)
* java/rmi/MarshalledObject.java (equals): Check hashcode first.

* java/rmi/server/RMIClassLoader.java (MyClassLoader): Create/Use
annotation.
(loadClass): Take String as codebases.
(getClassAnnotation): Use MyClassLoader annotations.
* java/rmi/server/UnicastRemoteObject.java (UnicastRemoteObject):
call exportObject(this).

* gnu/java/rmi/RMIMarshalledObjectOutputStream.java
(RMIMarshalledObjectOutputStream): set locBytesStream and locStream.
(setAnnotation): Don't set locBytesStream and locStream.
(replaceObject): Removed.
(flush): Don't test locStream.
(getLocBytes): LikeWise.
* gnu/java/rmi/dgc/DGCImpl.java: extends UnicastServerRef.
(leaseCache): New field.
(dirty): Use leaseCache.
(LeaseRecord): New inner class.
* gnu/java/rmi/registry/RegistryImpl.java (RegistryImpl): Don't
explicitly call exportObject().
* gnu/java/rmi/registry/RegistryImpl_Stub.java: set useNewInvoke to
false to communicate with Sun JDK130.
* gnu/java/rmi/server/ConnectionRunnerPool.java: Add CPU comment.
* gnu/java/rmi/server/RMIObjectInputStream.java
(UnicastConnectionManager): Removed field.
* gnu/java/rmi/server/RMIObjectOutputStream.java (replaceObject):
Use UnicastServer.getExportedRef().
* gnu/java/rmi/server/UnicastConnection.java (reviveTime): New field.
(expireTime): Likewise.
(CONNECTION_TIMEOUT): Likewise.
(disconnect): Call sock.close().
(isExpired): New method.
(resetTime): Likewise.
(run): Use do while loop and catch Exception for discardConnection().
* gnu/java/rmi/server/UnicastConnectionManager.java: Pool connections.
* gnu/java/rmi/server/UnicastRef.java: Lots of changes.
* gnu/java/rmi/server/UnicastRemoteCall.java: Lots of changes.
* gnu/java/rmi/server/UnicastServer.java (refcache): New field.
(exportObject): Use refcache.
(unexportObject): Likewise.
(getExportedRef): New method.
* gnu/java/rmi/server/UnicastServerRef.java (UnicastServerRef): New
constructor.
(exportObject): Save manager.serverobj.
(getStub): New method.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@58900 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
libjava/ChangeLog
libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java
libjava/gnu/java/rmi/dgc/DGCImpl.java
libjava/gnu/java/rmi/registry/RegistryImpl.java
libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java
libjava/gnu/java/rmi/server/ConnectionRunnerPool.java
libjava/gnu/java/rmi/server/RMIObjectInputStream.java
libjava/gnu/java/rmi/server/RMIObjectOutputStream.java
libjava/gnu/java/rmi/server/UnicastConnection.java
libjava/gnu/java/rmi/server/UnicastConnectionManager.java
libjava/gnu/java/rmi/server/UnicastRef.java
libjava/gnu/java/rmi/server/UnicastRemoteCall.java
libjava/gnu/java/rmi/server/UnicastServer.java
libjava/gnu/java/rmi/server/UnicastServerRef.java
libjava/java/rmi/MarshalledObject.java
libjava/java/rmi/server/RMIClassLoader.java
libjava/java/rmi/server/RemoteObject.java
libjava/java/rmi/server/UnicastRemoteObject.java

index 742977d..11ec52e 100644 (file)
@@ -1,5 +1,55 @@
 2002-11-07  Mark Wielaard  <mark@klomp.org>
 
+        Merge Orp RMI patches from Wu Gansha <gansha.wu@intel.com>
+       * java/rmi/MarshalledObject.java (equals): Check hashcode first.
+
+       * java/rmi/server/RMIClassLoader.java (MyClassLoader): Create/Use
+       annotation.
+       (loadClass): Take String as codebases.
+       (getClassAnnotation): Use MyClassLoader annotations.
+       * java/rmi/server/UnicastRemoteObject.java (UnicastRemoteObject):
+       call exportObject(this).
+
+       * gnu/java/rmi/RMIMarshalledObjectOutputStream.java
+       (RMIMarshalledObjectOutputStream): set locBytesStream and locStream.
+       (setAnnotation): Don't set locBytesStream and locStream.
+       (replaceObject): Removed.
+       (flush): Don't test locStream.
+       (getLocBytes): LikeWise.
+       * gnu/java/rmi/dgc/DGCImpl.java: extends UnicastServerRef.
+       (leaseCache): New field.
+       (dirty): Use leaseCache.
+       (LeaseRecord): New inner class.
+       * gnu/java/rmi/registry/RegistryImpl.java (RegistryImpl): Don't
+       explicitly call exportObject().
+       * gnu/java/rmi/registry/RegistryImpl_Stub.java: set useNewInvoke to
+       false to communicate with Sun JDK130.
+       * gnu/java/rmi/server/ConnectionRunnerPool.java: Add CPU comment.
+       * gnu/java/rmi/server/RMIObjectInputStream.java
+       (UnicastConnectionManager): Removed field.
+       * gnu/java/rmi/server/RMIObjectOutputStream.java (replaceObject):
+       Use UnicastServer.getExportedRef().
+       * gnu/java/rmi/server/UnicastConnection.java (reviveTime): New field.
+       (expireTime): Likewise.
+       (CONNECTION_TIMEOUT): Likewise.
+       (disconnect): Call sock.close().
+       (isExpired): New method.
+       (resetTime): Likewise.
+       (run): Use do while loop and catch Exception for discardConnection().
+       * gnu/java/rmi/server/UnicastConnectionManager.java: Pool connections.
+       * gnu/java/rmi/server/UnicastRef.java: Lots of changes.
+       * gnu/java/rmi/server/UnicastRemoteCall.java: Lots of changes.
+       * gnu/java/rmi/server/UnicastServer.java (refcache): New field.
+       (exportObject): Use refcache.
+       (unexportObject): Likewise.
+       (getExportedRef): New method.
+       * gnu/java/rmi/server/UnicastServerRef.java (UnicastServerRef): New
+       constructor.
+       (exportObject): Save manager.serverobj.
+       (getStub): New method.
+
+2002-11-07  Mark Wielaard  <mark@klomp.org>
+
        * java/lang/reflect/natField.cc (getBoolean): Use getType().
        (getByte): Likewise.
        (getShort): Likewise.
index 6639291..a721fc4 100644 (file)
@@ -61,42 +61,22 @@ public class RMIMarshalledObjectOutputStream extends RMIObjectOutputStream
   public RMIMarshalledObjectOutputStream(OutputStream objStream) throws IOException
   {
     super(objStream);
+    locBytesStream = new ByteArrayOutputStream(256);
+    locStream = new ObjectOutputStream(locBytesStream);
   }
   
   //This method overrides RMIObjectOutputStream's.
   protected void setAnnotation(String annotation) throws IOException{
-    synchronized(this){
-      if(locStream == null){
-       locBytesStream = new ByteArrayOutputStream();
-       locStream = new ObjectOutputStream(locBytesStream);
-      }
-    }
     locStream.writeObject(annotation);
   }
   
-  //This method overrides ObjectOutputStream's to replace Remote to RemoteStub 
-  protected Object replaceObject(Object obj) throws IOException
-  {
-    if((obj instanceof Remote) && !(obj instanceof RemoteStub))
-      {
-       UnicastServerRef ref = new UnicastServerRef(new ObjID(), 0, null);
-       try{
-         return ref.exportObject((Remote)obj);
-       }catch(Exception e){}
-      }
-    return obj;
-  }
-  
   public void flush() throws IOException {
     super.flush();
-    if(locStream != null)
-      locStream.flush();
+    locStream.flush();
   }
   
   public byte[] getLocBytes(){
-    if(locStream != null)
-      return locBytesStream.toByteArray();
-    return null;
+    return locBytesStream.toByteArray();
   }
   
 } // End of RMIMarshalledObjectOutputStream
index fba18c1..4216b64 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -46,24 +46,73 @@ import java.rmi.server.UnicastRemoteObject;
 import java.rmi.server.RMISocketFactory;
 import gnu.java.rmi.server.UnicastServerRef;
 
+import java.util.Hashtable;
+
+/**
+  * I let DGCImpl to extend UnicastServerRef, but not 
+  * UnicastRemoteObject, because UnicastRemoteObject must
+  * exportObject automatically.
+  */
 public class DGCImpl
-       extends UnicastRemoteObject implements DGC {
+    extends UnicastServerRef implements DGC {
 
-private static final long leaseValue = 600000L;
+    private static final long LEASE_VALUE = 600000L;
+    // leaseCache caches a LeaseRecord associated with a vmid
+    private Hashtable leaseCache = new Hashtable();
 
 public DGCImpl() throws RemoteException {
-       super(new UnicastServerRef(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory()));
+       super(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory());
 }
 
 public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) throws RemoteException {
        VMID vmid = lease.getVMID();
+       if (vmid == null)
+           vmid = new VMID();
+       long leaseValue = LEASE_VALUE;
+       //long leaseValue = lease.getValue();
     lease = new Lease(vmid, leaseValue);
-       System.out.println("DGCImpl.dirty - not completely implemented");
+        synchronized(leaseCache){
+            LeaseRecord lr = (LeaseRecord)leaseCache.get(vmid);
+            if (lr != null)
+                lr.reset(leaseValue);
+            else{
+                lr = new LeaseRecord(vmid, leaseValue);
+                leaseCache.put(vmid, lr);
+            }
+        }
+        
        return (lease);
 }
 
 public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong) throws RemoteException {
-       System.out.println("DGCImpl.clean - not implemented");
+  // Not implemented
 }
+    
+  /**
+   * LeaseRecord associates a vmid to expireTime.
+   */
+  private static class LeaseRecord{
+    private VMID vmid;
+    private long expireTime;
+    
+    LeaseRecord(VMID vmid, long leaseValue){
+      this.vmid = vmid;
+      reset(leaseValue);
+    }
+    
+    // reset expireTime
+    void reset(long leaseValue){
+      long l = System.currentTimeMillis();
+      expireTime = l + leaseValue;
+    }
 
-}
+    boolean isExpired(){
+      long l = System.currentTimeMillis();
+      if ( l > expireTime)
+       return true;
+      return false;
+    }
+        
+  } //End of LeaseRecord
+
+} //End of DGCImpl
index fdf4506..007d5a9 100644 (file)
@@ -64,7 +64,8 @@ public RegistryImpl(int port) throws RemoteException {
 
 public RegistryImpl(int port, RMIClientSocketFactory cf, RMIServerSocketFactory sf) throws RemoteException {
        super(new UnicastServerRef(new ObjID(ObjID.REGISTRY_ID), port, sf));
-       ((UnicastServerRef)getRef()).exportObject(this);
+       // The following is unnecessary, because UnicastRemoteObject export itself automatically.
+       //((UnicastServerRef)getRef()).exportObject(this);
 }
 
 public Remote lookup(String name) throws RemoteException, NotBoundException, AccessException {
index 33cb06a..45e10c4 100644 (file)
@@ -67,7 +67,7 @@ public final class RegistryImpl_Stub
     static {
         try {
             java.rmi.server.RemoteRef.class.getMethod("invoke", new java.lang.Class[] { java.rmi.Remote.class, java.lang.reflect.Method.class, java.lang.Object[].class, long.class });
-            useNewInvoke = true;
+            useNewInvoke = false;
             $method_bind_0 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("bind", new java.lang.Class[] {java.lang.String.class, java.rmi.Remote.class});
             $method_list_1 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("list", new java.lang.Class[] {});
             $method_lookup_2 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("lookup", new java.lang.Class[] {java.lang.String.class});
index df6363b..af7dc05 100644 (file)
@@ -91,6 +91,7 @@ class ConnectionRunnerPool
       
     }
   
+  // Should this value equal to number of CPU?
   private static int size = 5;
   private static int max_size = 10;
   
index 5913e92..3e862c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -50,23 +50,13 @@ import java.lang.reflect.Proxy;
 public class RMIObjectInputStream
        extends ObjectInputStream {
 
-UnicastConnectionManager manager;
-
-public RMIObjectInputStream(InputStream strm, UnicastConnectionManager man) throws IOException {
+public RMIObjectInputStream(InputStream strm) throws IOException {
        super(strm);
-       manager = man;
        enableResolveObject(true);
 }
 
-public RMIObjectInputStream(InputStream strm) throws IOException {
-       this(strm, UnicastConnectionManager.getInstance(0, null));
-}
-
 protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
        String annotation = (String)getAnnotation();
-       try{
-               return super.resolveClass(desc);
-       }catch(ClassNotFoundException _){};
        
        try {
                if(annotation == null)
@@ -90,24 +80,23 @@ protected Class resolveProxyClass(String intfs[])
         throws IOException, ClassNotFoundException
 {
     String annotation = (String)getAnnotation();
-    try{
-               return super.resolveProxyClass(intfs);
-       }catch(ClassNotFoundException _){};
        
     Class clss[] = new Class[intfs.length];
     if(annotation == null)
         clss[0] = RMIClassLoader.loadClass(intfs[0]);
     else
         clss[0] = RMIClassLoader.loadClass(annotation, intfs[0]);
+    
     //assume all interfaces can be loaded by the same classloader
     ClassLoader loader = clss[0].getClassLoader();
-    if(loader == null)
-        for(int i = 1; i < intfs.length; i++)
-            clss[i] = Class.forName(intfs[i]);    
-    else
-        for(int i = 1; i < intfs.length; i++)
-            clss[i] = loader.loadClass(intfs[i]);    
+    for (int i = 0; i < intfs.length; i++)
+        clss[i] = Class.forName(intfs[i], false, loader);
+        
+    try {
     return Proxy.getProxyClass(loader, clss);
+       } catch (IllegalArgumentException e) {
+           throw new ClassNotFoundException(null, e);
+       }  
 }
 
 protected Object readValue(Class valueClass) throws IOException, ClassNotFoundException {
@@ -134,4 +123,4 @@ protected Object readValue(Class valueClass) throws IOException, ClassNotFoundEx
         return readObject();
 }
 
-}
\ No newline at end of file
+}
index 71a2bac..97ac88a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -72,10 +72,9 @@ protected Object replaceObject(Object obj)
         throws IOException
 {
     if((obj instanceof Remote) && !(obj instanceof RemoteStub)){
-           UnicastServerRef ref = new UnicastServerRef(new ObjID(), 0, null);
-               try{
-                   return ref.exportObject((Remote)obj);
-               }catch(Exception e){}
+           UnicastServerRef ref = UnicastServer.getExportedRef((Remote)obj);
+           if (ref != null)
+                   return ref.getStub();
     }
     return obj;
 }
index e13bb68..14d28f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -61,6 +61,10 @@ DataOutputStream dout;
 ObjectInputStream oin;
 ObjectOutputStream oout;
 
+// reviveTime and expireTime make UnicastConnection pool-able
+long reviveTime = 0;
+long expireTime = Long.MAX_VALUE;
+
 UnicastConnection(UnicastConnectionManager man, Socket sock) {
        this.manager = man;
        this.sock = sock;
@@ -137,7 +141,7 @@ DataOutputStream getDataOutputStream() throws IOException {
 
 ObjectInputStream getObjectInputStream() throws IOException {
        if (oin == null) {
-               oin = new RMIObjectInputStream(din, manager);
+        oin = new RMIObjectInputStream(din);
        }
        return (oin);
 }
@@ -153,6 +157,7 @@ void disconnect() {
        try {
            if(oout != null)
                oout.close();
+        sock.close();
        }
        catch (IOException _) {
     }
@@ -164,17 +169,35 @@ void disconnect() {
        sock = null;
 }
 
+public static final long CONNECTION_TIMEOUT = 10000L;
+
+static boolean isExpired(UnicastConnection conn, long l){
+    if (l <= conn.expireTime )
+        return false;
+    return true;
+}
+
+static void resetTime(UnicastConnection conn){
+    long l = System.currentTimeMillis();
+    conn.reviveTime = l;
+    conn.expireTime = l + CONNECTION_TIMEOUT;
+}
+
 /**
  * We run connects on the server. Dispatch it then discard it.
  */
 public void run() {
+    do{
        try {
                UnicastServer.dispatch(this);
+            //don't discardConnection explicitly, only when
+            //  exception happens or the connection's expireTime 
+            //  comes
+        } catch (Exception e ){
                manager.discardConnection(this);
+            break;
        }
-       catch (Exception e) {
-               e.printStackTrace();
-       }
+    }while(true);
 }
 
 }
index 64fecdc..d54dcf1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -41,18 +41,25 @@ import java.rmi.server.RMISocketFactory;
 import java.rmi.server.RMIServerSocketFactory;
 import java.rmi.server.RMIClientSocketFactory;
 import java.rmi.RemoteException;
-import gnu.java.rmi.server.UnicastConnection;
-import java.util.Hashtable;
-import java.net.Socket;
-import java.net.ServerSocket;
 import java.io.IOException;
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
+import java.io.DataInputStream;
 import java.lang.Thread;
 import java.lang.Runnable;
 import java.net.InetAddress;
+import java.net.Socket;
+import java.net.ServerSocket;
 import java.net.UnknownHostException;
 
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import gnu.java.rmi.server.UnicastConnection;
+
 public class UnicastConnectionManager
        implements Runnable, ProtocolConstants {
 
@@ -60,15 +67,33 @@ private static String localhost;
 // use different maps for server/client type UnicastConnectionManager
 private static Hashtable servers = new Hashtable();
 private static Hashtable clients = new Hashtable();
+private ArrayList connections; //client connection pool
 
 // make serverThread volatile for poll
 private volatile Thread serverThread;
 private ServerSocket ssock;
 String serverName;
 int serverPort;
+
+static private Thread scavenger;
+
+// If client and server are in the same VM, serverobj represents server
+Object serverobj;
+
+private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory();
 private RMIServerSocketFactory serverFactory;
 private RMIClientSocketFactory clientFactory;
 
+// The following is for debug
+private static int ncsock = 0;    //count of client socket
+private static int nssock = 0;    //count of server socket
+private static int ncmanager = 0; //count of client manager
+private static int nsmanager = 0; //count of server manager
+
+private static final boolean debug = false;
+
+private static final Object GLOBAL_LOCK = new Object();
+
 static {
         try {
                 //Use host address instead of host name to avoid name resolving issues
@@ -78,16 +103,73 @@ static {
         catch (UnknownHostException _) {
                 localhost = "localhost";
         }
+        
+        
+}
+
+//Only one scavenger thread running globally
+private static void startScavenger(){
+    scavenger = new Thread(new Runnable(){
+        public void run(){
+            if (debug) System.out.println("************* start scavenger.");
+            boolean liveon = true;
+            while (liveon){
+                // Sleep for the expire timeout
+                try{
+                    Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT);
+                }catch(InterruptedException _ie){
+                    break;
+                }
+                liveon = false;
+                // Scavenge all clients' connections that're expired
+                Iterator iter = clients.values().iterator();
+                long l = System.currentTimeMillis();
+                try{
+                    while(iter.hasNext()){
+                        UnicastConnectionManager man = (UnicastConnectionManager)iter.next();
+                        ArrayList conns = man.connections;
+                        synchronized(conns) { // is the lock a little coarser?
+                            for (int last = conns.size() - 1;
+                                 last >= 0;
+                                 --last)
+                            {
+                                UnicastConnection conn = (UnicastConnection)conns.get(last);
+                                if (UnicastConnection.isExpired(conn, l)){
+                                    conns.remove(last);
+                                    conn.disconnect();
+                                    conn = null;   
+                                }else
+                                    liveon = true; //there're still live connections
+                            }
+                        }
+                    }
+                }catch(ConcurrentModificationException cme) {
+                    // handle it lazily
+                    liveon = true;
+                }
+            }
+            scavenger = null;
+            if (debug) System.out.println("************* exit scavenger.");
+        }
+    });
+    scavenger.start();
 }
 
+/**
+  * Client UnicastConnectionManager constructor
+  */
 private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
        ssock = null;
        serverName = host;
        serverPort = port;
        serverFactory = null;
        clientFactory = csf;
+    connections = new ArrayList();
 }
 
+/**
+  * Server UnicastConnectionManager constructor
+  */
 private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {
        try {
                ssock = ssf.createServerSocket(port);
@@ -115,7 +197,7 @@ private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {
 public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
 //System.out.println("getInstance: " + host + "," + port + "," + csf);
        if (csf == null) {
-               csf = RMISocketFactory.getSocketFactory();
+        csf = defaultSocketFactory;
        }
        // change host name to host address to avoid name resolving issues
        try{
@@ -126,7 +208,17 @@ public static synchronized UnicastConnectionManager getInstance(String host, int
        UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
        if (man == null) {
                man = new UnicastConnectionManager(host, port, csf);
+        if (debug) {
+            ncmanager++;
+            System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
+        }
                clients.put(key, man);
+        
+        // Detect if client and server are in the same VM, i.e., their keys are equal
+        UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
+        if(svrman != null){ // server and client are in the same VM
+            man.serverobj = svrman.serverobj;
+        }
        }
        return (man);
 }
@@ -138,12 +230,16 @@ public static synchronized UnicastConnectionManager getInstance(String host, int
 public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) {
 //System.out.println("getInstance: " + port + "," + ssf);
        if (ssf == null) {
-               ssf = RMISocketFactory.getSocketFactory();
+        ssf = defaultSocketFactory;
        }
        TripleKey key = new TripleKey(localhost, port, ssf);
        UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
        if (man == null) {
                man = new UnicastConnectionManager(port, ssf);
+        if (debug) {
+            nsmanager++;
+            System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n");
+        }
                // The provided port might not be the set port.
                key.port = man.serverPort;
                servers.put(key, man);
@@ -168,9 +264,14 @@ public UnicastConnection getConnection() throws IOException {
  */
 private UnicastConnection getServerConnection() throws IOException {
        Socket sock = ssock.accept();
+    sock.setTcpNoDelay(true); //??
        UnicastConnection conn = new UnicastConnection(this, sock);
        conn.acceptConnection();
-//System.out.println("Server connection " + conn);
+    if (debug){
+        nssock++;
+        System.out.println("\n\n ****** " + nssock + " server socks.\n\n");
+    }
+    //System.out.println("Server connection " + sock);
        return (conn);
 }
 
@@ -178,10 +279,38 @@ private UnicastConnection getServerConnection() throws IOException {
  * Make a conection from this client to the server.
  */
 private UnicastConnection getClientConnection() throws IOException {
+    ArrayList conns = connections;
+    UnicastConnection conn;
+    
+    synchronized(conns) {
+        int nconn = conns.size() - 1;
+    
+        // if there're free connections in connection pool
+        if(nconn >= 0) {
+            conn = (UnicastConnection)conns.get(nconn);
+            //Should we check if conn is alive using Ping??
+            conns.remove(nconn);
+            
+            // Check if the connection is already expired
+            long l = System.currentTimeMillis();
+            if (!UnicastConnection.isExpired(conn, l)){
+                return conn;
+            }else {
+                conn.disconnect();
+                conn = null;   
+            }
+        }
+    }
+    
        Socket sock = clientFactory.createSocket(serverName, serverPort);
-       UnicastConnection conn = new UnicastConnection(this, sock);
+    conn = new UnicastConnection(this, sock);
        conn.makeConnection(DEFAULT_PROTOCOL);
-//System.out.println("Client connection " + conn);
+    
+    if (debug) {
+        ncsock++;
+        System.out.println("\n\n ====== " + ncsock + " client socks.\n\n");
+    }
+
        return (conn);
 }
 
@@ -191,7 +320,19 @@ private UnicastConnection getClientConnection() throws IOException {
  */
 public void discardConnection(UnicastConnection conn) {
 //System.out.println("Discarding connection " + conn);
+    //conn.disconnect();
+    if (ssock != null) //server connection
        conn.disconnect();
+    else {
+        // To client connection, we'd like to return back to pool
+        UnicastConnection.resetTime(conn);
+        //Ensure there're only one scavenger globally
+        synchronized(GLOBAL_LOCK) {
+            connections.add(conn); //borrow this lock to garantee thread safety 
+            if (scavenger == null)
+                startScavenger();
+        }
+    }
 }
 
 /**
@@ -204,6 +345,8 @@ public void startServer() {
                        return;
                }
                serverThread = new Thread(this);
+        // The following is not necessary when java.lang.Thread's constructor do this.
+        // serverThread.setContextClassLoader(Thread.currentThread().getContextClassLoader());
        }
        serverThread.start();
 }
@@ -231,11 +374,11 @@ public void run() {
 //System.out.println("Waiting for connection on " + serverPort);
                        UnicastConnection conn = getServerConnection();
                        // use a thread pool to improve performance
-                       // (new Thread(conn)).start();
-                       ConnectionRunnerPool.dispatchConnection(conn);
+            //ConnectionRunnerPool.dispatchConnection(conn);
+            (new Thread(conn)).start();
                }
                catch (Exception e) {
-                       // e.printStackTrace();
+            e.printStackTrace();
                }
        }
 }
@@ -254,8 +397,9 @@ void write(ObjectOutput out) throws IOException {
 static UnicastConnectionManager read(ObjectInput in) throws IOException {
         String host = in.readUTF();
         int port = in.readInt();
-       RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
-        return (getInstance(host, port, csf));
+        //RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
+        //return (getInstance(host, port, csf));
+        return (getInstance(host, port, null));
 }
 
 }
@@ -288,7 +432,7 @@ public boolean equals(Object obj) {
                TripleKey other = (TripleKey)obj;
                if (this.host.equals(other.host) &&
                    this.other == other.other &&
-                   (this.port == other.port || this.port == 0 || other.port == 0)) {
+            (this.port == other.port /* || this.port == 0 || other.port == 0*/)) {
                        return (true);
                }
        }
index d6cda49..9ab020d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -62,6 +62,8 @@ import java.io.ObjectOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 
+import java.lang.reflect.InvocationTargetException;
+
 public class UnicastRef
        implements RemoteRef, ProtocolConstants {
 
@@ -69,9 +71,10 @@ public ObjID objid;
 UnicastConnectionManager manager;
 
 /**
- * Used by serialization.
+ * Used by serialization, and let subclass capable of having default constructor
  */
-private UnicastRef() {
+//private 
+UnicastRef() {
 }
 
 public UnicastRef(ObjID objid, String host, int port, RMIClientSocketFactory csf) {
@@ -84,6 +87,21 @@ public UnicastRef(ObjID objid) {
 }
 
 public Object invoke(Remote obj, Method method, Object[] params, long opnum) throws Exception {
+    // Check if client and server are in the same VM, then local call can be used to
+    // replace remote call, but it's somewhat violating remote semantic.
+    Object svrobj = manager.serverobj;
+    if(svrobj != null){
+        //local call
+               Object ret = null;
+               try{
+                   ret = method.invoke(svrobj, params);
+               }catch(InvocationTargetException e){
+                   throw (Exception)e.getTargetException();
+               }
+               //System.out.println("\n\n ***** local call: " + method + "\nreturn: " + ret + "\n\n");
+               return ret;
+       }
+       //System.out.println("***************** remote call:" + manager.serverPort);
        return (invokeCommon(obj, method, params, -1, opnum));
 }
 
@@ -107,18 +125,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
                objid.write(out);
                out.writeInt(opnum);
                out.writeLong(hash);
-               /*
-               if (params != null) {
-                       for (int i = 0; i < params.length; i++) {
-                               if (params[i] instanceof UnicastRemoteObject) {
-                                       out.writeObject(UnicastRemoteObject.exportObject((UnicastRemoteObject)params[i]));
-                               }
-                               else {
-                                       out.writeObject(params[i]);
-                               }
-                       }
-               }
-               */
+               
                // must handle primitive class and their wrapper classes
                Class clss[] = method.getParameterTypes();
            for(int i = 0; i < clss.length; i++)
@@ -137,26 +144,30 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
        UID ack;
        try {
                din = conn.getDataInputStream();
-               if (din.readUnsignedByte() != MESSAGE_CALL_ACK) {
-                       throw new RemoteException("Call not acked");
+               
+               if ((returncode = din.readUnsignedByte()) != MESSAGE_CALL_ACK) {
+                   conn.disconnect();
+                       throw new RemoteException("Call not acked:" + returncode);
                }
 
                in = conn.getObjectInputStream();
-
                returncode = in.readUnsignedByte();
                ack = UID.read(in);
-               //returnval = in.readObject();
+
                Class cls = method.getReturnType();
         if(cls == Void.TYPE){
             returnval = null;
+            in.readObject();
         }else
             returnval = ((RMIObjectInputStream)in).readValue(cls);
+
        }
        catch (IOException e3) {
+           //for debug: e3.printStackTrace();
                throw new RemoteException("call return failed: ", e3);
        }
 
-    /* if DGCAck is necessary
+    /* if DGCAck is necessary??
     //According to RMI wire protocol, send a DGCAck 
     // to indicate receiving return value
     dout.writeByte(MESSAGE_DGCACK);
@@ -166,7 +177,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
     
        manager.discardConnection(conn);
 
-       if (returncode != RETURN_ACK) {
+       if (returncode != RETURN_ACK && returnval != null) {
                throw (Exception)returnval;
        }
 
@@ -177,7 +188,18 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
  * @deprecated
  */
 public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash) throws RemoteException {
-       return (new UnicastRemoteCall(obj, opnum, hash));
+    UnicastConnection conn;
+    
+       try {
+               conn = manager.getConnection();
+       }
+       catch (IOException e1) {
+               throw new RemoteException("connection failed to host: " + manager.serverName, e1);
+       }
+
+    //obj: useless?
+
+       return (new UnicastRemoteCall(conn, objid, opnum, hash));
 }
 
 /**
@@ -185,15 +207,19 @@ public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash
  */
 public void invoke(RemoteCall call) throws Exception {
        UnicastRemoteCall c = (UnicastRemoteCall)call;
-       Object ret = invokeCommon((Remote)c.getObject(), (Method)null, c.getArguments(), c.getOpnum(), c.getHash());
-       c.setReturnValue(ret);
+       call.executeCall();
 }
 
 /**
  * @deprecated
  */
 public void done(RemoteCall call) throws RemoteException {
-       /* Does nothing */
+       UnicastRemoteCall c = (UnicastRemoteCall)call;
+       try{
+           c.done();
+       } catch(IOException e){}
+    UnicastConnection conn = c.getConnection();
+       manager.discardConnection(conn);
 }
 
 public void writeExternal(ObjectOutput out) throws IOException {
index 200538d..734002a 100644 (file)
@@ -38,14 +38,24 @@ exception statement from your version. */
 package gnu.java.rmi.server;
 
 import java.lang.Exception;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.IOException;
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
 import java.io.StreamCorruptedException;
 import java.rmi.server.RemoteCall;
+import java.rmi.RemoteException;
+import java.rmi.MarshalException;
+import java.rmi.UnmarshalException;
+import java.rmi.server.UID;
+import java.rmi.server.ObjID;
+import java.rmi.server.RemoteObject;
+
 import java.util.Vector;
 
-public class UnicastRemoteCall implements RemoteCall
+public class UnicastRemoteCall
+       implements RemoteCall, ProtocolConstants
 {
 
   private UnicastConnection conn;
@@ -56,6 +66,9 @@ public class UnicastRemoteCall implements RemoteCall
   private Vector vec;
   private int ptr;
 
+  private ObjectOutput oout;
+  private ObjectInput oin;
+
   /**
    * Incoming call.
    */
@@ -67,30 +80,71 @@ public class UnicastRemoteCall implements RemoteCall
   /**
    * Outgoing call.
    */
-  UnicastRemoteCall(Object obj, int opnum, long hash)
+  UnicastRemoteCall(UnicastConnection conn, ObjID objid, int opnum, long hash)
+    throws RemoteException
   {
-    this.object = obj;
+    this.conn = conn;
     this.opnum = opnum;
     this.hash = hash;
+    
+    // signal the call when constructing
+    try
+      {
+       DataOutputStream dout = conn.getDataOutputStream();
+       dout.write(MESSAGE_CALL);
+       
+       oout = conn.getObjectOutputStream();
+       objid.write(oout);
+       oout.writeInt(opnum);
+       oout.writeLong(hash);
+      }
+    catch(IOException ex)
+      {
+       throw new MarshalException("Try to write header but failed.", ex);
+      }
   }
-
+  
+  UnicastConnection getConnection()
+  {
+    return conn;
+  }
+  
   public ObjectOutput getOutputStream() throws IOException
   {
-    vec = new Vector();
-    return new DummyObjectOutputStream();
+    if (conn != null)
+      {
+       if(oout == null)
+         return (oout = conn.getObjectOutputStream());
+       else
+         return oout;
+      }
+    else
+      {
+       vec = new Vector();
+       return (new DummyObjectOutputStream());
+      }
   }
 
   public void releaseOutputStream() throws IOException
   {
-    // Does nothing.
+    if(oout != null)
+      oout.flush();
   }
 
   public ObjectInput getInputStream() throws IOException
   {
     if (conn != null)
-      return conn.getObjectInputStream();
-    ptr = 0;
-    return new DummyObjectInputStream();
+      {
+       if(oin == null)
+         return (oin = conn.getObjectInputStream());
+       else
+         return oin;
+      }
+    else
+      {
+       ptr = 0;
+       return (new DummyObjectInputStream());
+      }
   }
 
   public void releaseInputStream() throws IOException
@@ -104,15 +158,57 @@ public class UnicastRemoteCall implements RemoteCall
     vec = new Vector();
     return new DummyObjectOutputStream();
   }
-
+  
   public void executeCall() throws Exception
   {
-    throw new Error("Not implemented");
+    byte returncode;
+    ObjectInput oin;
+    try
+      {
+       releaseOutputStream();
+       DataInputStream din = conn.getDataInputStream();
+        if (din.readByte() != MESSAGE_CALL_ACK)
+           throw new RemoteException("Call not acked");
+
+        oin = getInputStream();
+        returncode = oin.readByte();
+        UID.read(oin);
+      }
+    catch(IOException ex)
+      {
+        throw new UnmarshalException("Try to read header but failed:", ex);
+      }
+    
+    //check return code
+    switch(returncode)
+      {
+      case RETURN_ACK: //it's ok
+       return;
+      case RETURN_NACK:
+       Object returnobj;
+       try
+         {
+           returnobj = oin.readObject();
+         }
+       catch(Exception ex2)
+         {
+           throw new UnmarshalException
+             ("Try to read exception object but failed", ex2);
+         }
+       
+       if(!(returnobj instanceof Exception))
+         throw new UnmarshalException("Should be Exception type here: "
+                                      + returnobj);
+       throw (Exception)returnobj;
+       
+      default:
+       throw new UnmarshalException("Invalid return code");
+      }
   }
 
   public void done() throws IOException
   {
-    /* Does nothing */
+    // conn.disconnect();
   }
 
   Object returnValue()
index 15c622f..baa1ef1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -45,6 +45,7 @@ import java.io.IOException;
 import java.net.InetAddress;
 import java.util.Hashtable;
 import java.net.UnknownHostException;
+import java.rmi.Remote;
 import java.rmi.server.ObjID;
 import java.rmi.server.UnicastRemoteObject;
 import java.rmi.server.UID;
@@ -56,27 +57,36 @@ import gnu.java.rmi.dgc.DGCImpl;
 public class UnicastServer
        implements ProtocolConstants {
 
-static private Hashtable objects = new Hashtable();
+static private Hashtable objects = new Hashtable();  //mapping OBJID to server ref
+static private Hashtable refcache = new Hashtable(); //mapping obj itself to server ref
 static private DGCImpl dgc;
 
 public static void exportObject(UnicastServerRef obj) {
        startDGC();
        objects.put(obj.objid, obj);
+       refcache.put(obj.myself, obj);
        obj.manager.startServer();
 }
 
 // FIX ME: I haven't handle force parameter
 public static boolean unexportObject(UnicastServerRef obj, boolean force) {
        objects.remove(obj.objid);
+       refcache.remove(obj.myself);
        obj.manager.stopServer();
        return true;
 }
 
+public static UnicastServerRef getExportedRef(Remote remote){
+    return (UnicastServerRef)refcache.get(remote);
+}
+
 private static synchronized void startDGC() {
        if (dgc == null) {
                try {
                        dgc = new DGCImpl();
-                       ((UnicastServerRef)dgc.getRef()).exportObject(dgc);
+                       // Changed DGCImpl to inherit UnicastServerRef directly
+                       //((UnicastServerRef)dgc.getRef()).exportObject(dgc);
+                       dgc.exportObject(dgc);
                }
                catch (RemoteException e) {
                        e.printStackTrace();
index 196f969..4f64452 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -63,6 +63,8 @@ import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.Hashtable;
 
 public class UnicastServerRef
@@ -71,11 +73,18 @@ public class UnicastServerRef
 
 final static private Class[] stubprototype = new Class[] { RemoteRef.class };
 
-Remote myself;
+Remote myself; //save the remote object itself
 private Skeleton skel;
 private RemoteStub stub;
 private Hashtable methods = new Hashtable();
 
+/**
+ * Used by serialization.
+ */
+UnicastServerRef()
+{
+}
+
 public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) {
        super(id);
        manager = UnicastConnectionManager.getInstance(port, ssf);
@@ -84,6 +93,9 @@ public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) {
 public RemoteStub exportObject(Remote obj) throws RemoteException {
        if (myself == null) {
                myself = obj;
+               // Save it to server manager, to let client calls in the same VM to issue
+               //  local call
+               manager.serverobj = obj;
 
                // Find and install the stub
                Class cls = obj.getClass();
@@ -112,6 +124,10 @@ public RemoteStub exportObject(Remote remote, Object obj)
        return exportObject(remote);
 }
 
+public RemoteStub getStub(){
+    return stub;
+}
+
 
 public boolean unexportObject(Remote obj, boolean force) throws RemoteException {
     // Remove all hashes of methods which may be called.
index 4c9a9cc..9f966b9 100644 (file)
@@ -78,6 +78,10 @@ public final class MarshalledObject
   {
     if(obj == null || !(obj instanceof MarshalledObject) )
       return false;
+
+    // hashCode even differs, don't do the time-consuming comparisons
+    if (obj.hashCode() != hash)
+      return false;
     
     MarshalledObject aobj = (MarshalledObject)obj;
     if (objBytes == null || aobj.objBytes == null)
index da8f52c..1b00970 100644 (file)
@@ -43,39 +43,72 @@ import java.net.URLClassLoader;
 import java.io.IOException;
 import java.io.DataInputStream;
 import java.net.MalformedURLException;
-import java.util.StringTokenizer;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Hashtable;
 import java.util.Map;
+import java.util.StringTokenizer;
 import java.util.WeakHashMap;
-import java.util.ArrayList;
 
 public class RMIClassLoader
 {
 
   static private class MyClassLoader extends URLClassLoader
   {
+
+    private MyClassLoader(URL[] urls, ClassLoader parent, String annotation)
+    {
+      super(urls, parent);
+      this.annotation = annotation;
+    }
+
     private MyClassLoader(URL[] urls, ClassLoader parent)
     {
       super (urls, parent);
+      this.annotation = urlToAnnotation(urls);
     }
 
-    Class defineClass(String name, byte[] data)
+    public static String urlToAnnotation(URL[] urls)
     {
-      return defineClass(name, data, 0, data.length);
+      if (urls.length == 0)
+       return null;
+
+      StringBuffer annotation = new StringBuffer(64*urls.length);
+      for(int i = 0; i < urls.length; i++)
+       {
+         annotation.append(urls[i].toExternalForm());
+         annotation.append(' ');
+       }
+
+      return annotation.toString();
+    }
+
+    public final String getClassAnnotation(){
+      return annotation;
     }
+
+    private final String annotation;
+
   }
 
   private static Map cacheLoaders; //map annotations to loaders
-  private static Map cacheClasses; //map loader to classes that the loader loaded+
+  private static Map cacheAnnotations; //map loaders to annotations
+
+  //defaultAnnotation is got from system property
+  // "java.rmi.server.defaultAnnotation"
   private static String defaultAnnotation;
+  //URL object for defaultAnnotation
   private static URL defaultCodebase;
+  //class loader for defaultAnnotation
   private static MyClassLoader defaultLoader;
   
   static
   {
-    cacheLoaders = Collections.synchronizedMap(new WeakHashMap(5)); 
-    cacheClasses = Collections.synchronizedMap(new WeakHashMap(5));
+    // 89 is a nice prime number for Hashtable initial capacity
+    cacheLoaders = new Hashtable(89);
+    cacheAnnotations = new Hashtable(89);
+    
     defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation");
     try 
       {
@@ -89,9 +122,8 @@ public class RMIClassLoader
     if (defaultCodebase != null)
       {
         defaultLoader = new MyClassLoader(new URL[]{ defaultCodebase },
-                                         Thread.currentThread().getContextClassLoader());
+                                         null, defaultAnnotation);
         cacheLoaders.put(defaultAnnotation, defaultLoader);
-        cacheClasses.put(defaultLoader, Collections.synchronizedMap(new WeakHashMap())); 
       }
   }
   
@@ -104,91 +136,76 @@ public class RMIClassLoader
     return (loadClass("", name));
   }
 
-  public static Class loadClass(URL codebase, String name) 
+  public static Class loadClass(String codebases, String name) 
     throws MalformedURLException, ClassNotFoundException 
   {
-    URL u = new URL(codebase, name + ".class");
+    Class c = null;
+    ClassLoader loader = Thread.currentThread().getContextClassLoader();
+    //try context class loader first
     try 
       {
-       URLConnection conn = u.openConnection();
-       DataInputStream strm = new DataInputStream(conn.getInputStream());
-       byte data[] = new byte[conn.getContentLength()];
-       strm.readFully(data);
-       return (defaultLoader.defineClass(name, data));
-      }
-    catch (IOException _) 
-      {
-       throw new ClassNotFoundException(name);
+           c = loader.loadClass(name);       
       }
-  }
-  
-  public static Class loadClass(String codebases, String name) 
-    throws MalformedURLException, ClassNotFoundException 
-  {
-    ClassLoader loader = (ClassLoader)cacheLoaders.get(codebases);
-    if (loader == null)
+    catch(ClassNotFoundException e) {}
+
+    if (c != null)
+      return c;
+
+    if (codebases.length() == 0) //==""
+      loader = defaultLoader;
+    else 
       {
-       if (codebases != "")
+       loader = (ClassLoader)cacheLoaders.get(codebases);
+       if (loader == null)
          {
-           //codebases are separated by " "
+           //create an entry in cacheLoaders mapping a loader to codebases.
+            
+           // codebases are separated by " "
            StringTokenizer tok = new StringTokenizer(codebases, " "); 
            ArrayList urls = new ArrayList();
            while (tok.hasMoreTokens())
              urls.add(new URL(tok.nextToken()));
-           
+  
            loader = new MyClassLoader((URL[])urls.toArray(new URL[urls.size()]),
-                                      Thread.currentThread().getContextClassLoader());
+                                       null, codebases);
            cacheLoaders.put(codebases, loader);
-           cacheClasses.put(loader, Collections.synchronizedMap(new WeakHashMap())); 
-         }
-       else
-         {
-           //if codebases is empty, construct a classloader 
-           // based on current context classloader,
-           // and we won't cache classloader for empty codebases
-           loader = new MyClassLoader(new URL[]{ defaultCodebase },
-                                      Thread.currentThread().getContextClassLoader());
          }
       }
 
-    Class c = null;
-    Map classes = (Map)cacheClasses.get(loader);
-    if (classes != null)
-      {
-        c = (Class)classes.get(name);
-        if (c == null)
-         {
-            c = loader.loadClass(name);
-            classes.put(name, c); 
-         }
-      }else
-        c = loader.loadClass(name);
-    
-    return c;
+    return loader != null ? loader.loadClass(name) : Class.forName(name);
   }
   
   public static String getClassAnnotation(Class cl)
   {
     ClassLoader loader = cl.getClassLoader();
-    if (loader == null)
+    if (loader == null || loader == ClassLoader.getSystemClassLoader())
       {
-       if (defaultCodebase != null)
-         return defaultCodebase.toExternalForm();
-       else
-         return null;
+       return null; //??
+      }
+       
+    if (loader instanceof MyClassLoader)
+      {
+       return ((MyClassLoader)loader).getClassAnnotation();
       }
+       
+    String s = (String)cacheAnnotations.get(loader);
+    if (s != null)
+      return s;
+           
     if (loader instanceof URLClassLoader)
       {
        URL[] urls = ((URLClassLoader)loader).getURLs();
        if(urls.length == 0)
          return null;
-       StringBuffer annotation = new StringBuffer(urls[0].toExternalForm());
-       for(int i = 1; i < urls.length; i++)
+
+       StringBuffer annotation = new StringBuffer(64*urls.length);
+       for(int i = 0; i < urls.length; i++)
          {
-           annotation.append(' ');
            annotation.append(urls[i].toExternalForm());
+           annotation.append(' ');
          }
-       return annotation.toString();
+       s = annotation.toString();
+       cacheAnnotations.put(loader, s);
       }
     return null;
   }
index 8ae93ff..a1febf2 100644 (file)
@@ -127,11 +127,11 @@ public boolean equals(Object obj) {
          }
        catch (InstantiationException e1) 
          {
-           throw new UnmarshalException("failed to create ref");
+           throw new UnmarshalException("failed to create ref", e1);
          }
        catch (IllegalAccessException e2) 
          {
-           throw new UnmarshalException("failed to create ref");
+           throw new UnmarshalException("failed to create ref", e2);
          }
        ref.readExternal(in);
       }
index a9c4f35..aefe970 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -67,16 +67,12 @@ protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSoc
   //this.csf = csf;
   //this.ssf = ssf;
   this.ref = new UnicastServerRef(new ObjID(), port, ssf);
-  //Should we export it here?
-  // if we export, we got infinite recursive call:
-  //  UnicastRemoteObject.<init>->...->UnicastServer.startDGC()->UnicastRemoteObject.<init>->...
-  //exportObject(this);
+  exportObject(this);
 }
 
 protected UnicastRemoteObject(RemoteRef ref) throws RemoteException {
        super((UnicastServerRef)ref);
-       //Should we export it here?
-       //exportObject(this);
+       exportObject(this);
 }
 
 public Object clone() throws CloneNotSupportedException {