Known Issues
This is the list of known issues
1 13/10/2005 - java.rmi.server.UID - Gonzalo Ortega
2 13/10/2005 - ar.org.fitc.rmi.utils.Utils - Horacio de Oro
3 3/11/2005 - ar.org.fitc.rmi.net.StreamProtocolHandler - Gustavo Petri
4 7/11/2005 - Use of ServerRef interface - Gonzalo Ortega
5 10/11/2005 - java.rmi.server.hostname during Object Exportation - Gonzalo Ortega
6 17/11/2005 - ClassLoaderSpi - Gustavo Petri
7 21/11/2005 - Exportation of multiple Registries in the same process. - Gonzalo Ortega
8 23/11/2005 - RMIClassLoaderSpi.loadProxyClass - Gustavo Petri
9 25/11/2005 - RemoteObject Serialization implementation changes - Gonzalo Ortega
10 30/11/2005 - DGC Memory Leaks? - Gustavo Petri
11 19/12/2005 - Client's Default Server - Gustavo Petri
12 02/01/2006 - Client Garbage Collector Implementation issues - Gonzalo Ortega
13 05/01/2006 - Client Garbage Collector - Gonzalo Ortega
14 15/02/2006 - RMIDefaultSocketFactory/RMIServerSocket - Gonzalo Ortega
15 01/03/2006 - Connection reusing: ObjectOutputStream opening and closing issues during call - Gonzalo Ortega
16 15/03/2006 - HTTP through CGI tunneling fallback issue - Gonzalo Ortega
13/10/2005 - java.rmi.server.UID - Gonzalo Ortega
The "unique" filed inside the UID is supposed to be a unique identifier inside a host. Such identifier is impossible to get from Java. Possible solutions were:
a) To use a random number.
b) To use the hash of and Object() instance. This hash is generated from the memory address of the object. Two objects inside the same host won't have the same memory address, so this could be a good approach.
Finally, option b) was implemented. We are actually using the hash of an Object instance. We are relying in the fact that the hash is generated from the memory address of the object, and we assume that this address is unique inside a host.
13/10/2005 - ar.org.fitc.rmi.utils.Utils - Horacio de Oro
We have NOT implemented the SHA1 algorithm. We're using 'MessageDigest.getInstance("SHA1")'.
An InternalError is thrown if an unrecoverable error is detected.
3/11/2005 - ar.org.fitc.rmi.net.StreamProtocolHandler - Gustavo Petri
Deficiencies in RMI (JRMP) wire protocol specification
7/11/2005 - Use of ServerRef interface - Gonzalo Ortega
API Specification doesn't define the specific use for this interface. Method exportObject defined in this interface seems to be obsolete, since returns a RemoteStub object, and then only one of the possible exportation scenario is covered by this method (all other exportation situations, returns a Remote object; therefore this method isn't suitable for implement them), for that reason the use of this interface seems to be unnecessary for exportation purposes. Since is logical to think that will be one ServerRef per exported remote object, the ServerRefImpl object seems suitable for dispatching the remote method invocation to its univocal exported remote object (acting in same way as a "dynamic" skeleton for the object). The executeCall() method (dispatcher) and all the data needed for its execution will be placed then in the object implementing the ServerRef interface, as stated in Design Revision 1
10/11/2005 - java.rmi.server.hostname during Object Exportation - Gonzalo Ortega
When exporting an object, setting the java.rmi.server.hostname property doesn't cause the expected effect. Setting this property to an invalid host name doesn't stop the exportation process, and the object is exported ok in localhost, but then the clients stubs are trying to find the remote server in the invalid path (as specified in the property value). The specification doesn't mention anything about exporting an object with a wrong name set in the java.rmi.server.hostname property. Sun's implementation behaves in the above way, and we are following that behavior.
17/11/2005 - ClassLoaderSpi - Gustavo Petri
The API Specification always assumes that the property java.rmi.server.codebase is correctly setted, and it does not specify what to do when returns null. In this case we simply return Thread.currentThread().getContextClassLoader(), though it is not specified.
21/11/2005 - Exportation of multiple Registries in the same process. - Gonzalo Ortega
The exportation of multiple registries in the same process isn't allowed.
The current design doesn't allow more than one remote object per ObjID (the relation between an ObjID and its represented object is univocal) therefore two different objects with the same ObjID aren't allowed. (The ObjID API specification doesn't specify the scope of uniqueness for a well-known ObjID, but for "regular" ObjIDs said that "an ObjID is unique over time with respect to the host it is generated on"). Having more than one registry exported in the same RMI Runtime would need the existence of more than one ObjID(0) (the well known ObjID for the Registry) in the same RMI Runtime, and for different remote objects (registries), which is, in same way, opposite to the concept of ObjID itself. RMI Specification doesn't specify how many registries are allowed per process (or if should be more than one), but Sun's implementation allow multiple registries.
23/11/2005 - RMIClassLoaderSpi.loadProxyClass - Gustavo Petri
It is not clear from the API whether the terms "resolve", "define" are used in the same way as defined in the Class ClassLoader.
The API diferetiates two different behaviors, depending on whether the defaultLoader can resolve all the interfaces or the codebase ClassLoader can resolve all the interfaces. Form this point it is not clear if all the interfaces should be resolved be the same or different loaders. The current solution implemented loads the interfaces using the loadClass method of the same provider, which implies it can resolve it from different loaders. Besides, there is no an a priori way to know if a ClassLoader can resolve a set of classes, so the only way to know if that condition is true is to try to load the classes untill some one fails. Also it is not clear that every interface requested in the parameters should be implemented, though it seems anti-intuitive, it is not explicitly stated so it could be a possibility. The current implementation raises an exception if it can not implement every interface.
25/11/2005 - RemoteObject Serialization implementation changes - Gonzalo Ortega
The initial implementation of the RemoteObject serialization methods (writeObject and readObject), were accidentally not implemented as specified. In fact the implementation was pretty simple, the RemoteObject.writeObject() method wrote all the non transient instance variables of the RemoteObject instance being serialized, and then if the stream in which it was writing was a RMIObjectOutputStream, it wrote the RemoteRef transient instance by calling to the RMIObjectOutputStream.writeObject() method. Note that if the RemoteObject being serialized was an instance of UnicastRemoteObject, the RMIObjectOuputStream serialization mechanism translated it to its corresponding stub if the object being serialized was already exported locally.
Though pretty simple this is not the procedure followed by the RMI API specification. Instead the API sends initial headers in the stream that indicate whether the object being serialized is a RemoteStub (or RemoteInvocationHandler), an activatable object, or a UnicastRemoteObject itself. In fact they distinguish the cases of an object exported using custom socket factories or not. This seems a bit unnecessary because it can be entirely resolved using the ObjectOutputStream.writeObject() method.
Accordingly to the "type" of the object received ("UnicastRef", "UnicastRef2", "ActivatableRef", "UnicastServerRef", "UnicastServerRef2") the serialized instances might vary. As far as we had a single UnicastRef implementation and the specification states that an implementation-specific instance of a class related to the type of the reference must be created and then the readExternal() method of that instance must be called, we had to do a refactoring of the implemented classes to match the specification. Maybe behind the specification's "tags" (UnicastRef, UnicastRef2, etc) are compatibility issues that we are not clearly seeing at the moment.
30/11/2005 - DGC Memory Leaks? - Gustavo Petri
In the API Specification for the java.rmi.dgc.DGC.clean() it is mentioned that when the boolean parameter strong is true the sequenceNumber the calling VM (with its corresponding VMID) should be remembered. This happens when a previously issued dirty call failed in that client. This implies that if the dirty call has been lost the server will never remove that sequenceNumber from its table. In the long run this implies that memory will be stored for objects which will never be reused.
We hope to solve this issue by defining a maximun time to live for the sequenceNumber of an unordered clean call.
19/12/2005 - Client's Default Server - Gustavo Petri
The JRMP protocol send a Client's Default Server Endpoint identifier in the initial handshaking. As far as this seems only to be useful for the multiplexed version of the Transport Layer (which we are not to implement yet), we are currently discarding this data.
02/01/2006 - Client Garbage Collector Implementation issues - Gonzalo Ortega
- The Client Garbage Collector uses a java.util.Timer object for scheduling all the dirty calls in the lease renewal process mechanism. Since the Timer's implementation uses only one thread for running all its tasks, it means that if a dirty call delays for any reason, this could interfere with the renewal of the leases of the other scheduled references.
- In order to keep unique instances of a stub in client DGC, the implementation is heavily synchronized. This strong synchronization could produce some performance issues when a great number of stubs are received simultaneously. Further depuration is needed in order to optimize this behaviour.
05/01/2006 - Client Garbage Collector - Gonzalo Ortega
RMI API states that a client should use a null value if it is unable to generate a VMID; and then send the dirty call with that null VMID, in order to receive a VMID from the server. The only way to know if the generated VMID is somehow "unique" is calling the deprecated VMID.isUnique() method, as long the VMID constructor doesn't throw any exception. (It always success) In addition, the API doesn't specify what should happen if the server is unable to generate a unique VMID too.
15/02/2006 - RMIDefaultSocketFactory/RMIServerSocket - Gonzalo Ortega
When accepting a new incoming connection in the server, after the accept() method unblocks, we are currently reading four bytes from the socket's input stream, in order to determine if the accepted connection is a direct JRMP connection (JRMI bytes should be received) or a HTTP connection (HTTP bytes should be received), and instantiate the appropriate socket class to manage it. This reading is done in the same thread that the accept() method is executed, before launching the new thread which will serve the incoming call. This means that if for some reason those four bytes are not received, the read() operations could block avoiding other incoming connections to be received in that port, until timeout exceptions unblocks the blocked operations.
01/03/2006 - Connection reusing: ObjectOutputStream opening and closing issues during call - Gonzalo Ortega
Due to connection reusing feature supported by the transport layer, it is necessary to keep used sockets (and its corresponding input and output streams) open in a pool for future re-utilization. Necessary ObjectOutputStream used to serialize call arguments (as stated by Bug Report ID: 4050017 - RMI SPEC: Could it be made clearer that entire "CallData" uses object serialization, http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4050017; the entire "CallData" protocol element is sent through an ObjectOuputStream) should be open, used (to send "CallData" information), and then closed and discarded; keeping the underlying socket's OutputStream pooled for future reuse. The problem is that ObjectOutputStream.close() method's API does not specify clearly if the close() statement is propagated to the underlying output stream. If that occurs, the underlying output stream will be closed too, preventing future reuse. As long Harmony's implementation of ObjectOuputStream closes the underlying stream on its close() method, calling close() after sending "CallData" information will effectively avoid future stream reutilization. As suggested in http://archives.java.sun.com/cgi-bin/wa?A2=ind0004&L=rmi-users&D=0&I=-3&P=31671 , we actually discard the ObjectOuputStream after finishing the call.
15/03/2006 - HTTP through CGI tunneling fallback issue - Gonzalo Ortega
RMI specification states that the transport layer should use a three tiered strategy when connecting to a server; from the API: "The default socket factory implementation used goes through a three-tiered approach to creating client sockets" This falling strategy is known as RMI's "fallback" transport mechanism; concretely, it will try a direct connection to the server host and port first, if it fails, a connection to the proxy using HTTP, and if that connection fails, a connection to the proxy using HTTP redirecting the call through a CGI script on a web server. There is a problem falling from the second to the third case. Since the connection is always accepted by the proxy in the "http to proxy" case (if there is a proxy, of course), the fallback will never reach the third case, even if the call request fails. Anyway, HTTP through CGI approach could still be invoked setting the appropriate transport implementation property. Sun's implementation seems to behave in a similar way.