Thanks to those who answered my DuplicateKeyException question, your advice has been most helpful. I have an RMI question that I hope you can help with. Although this is a general question there is a specific issue for URLyBird as well. Section 3.2 of the RMI specification states that: "A method dispatched by the RMI runtime to a remote object implementation may or may not execute in a separate thread. The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads. Since remote method invocation on the same remote object may execute concurrently, a remote object implementation needs to make sure its implementation is thread-safe." It seems to me that there are more serious implications to this characteristic of RMI than the specification suggests. In addition to stating that an implementation must make sure it is thread safe it should also state that an implementation must make sure it is multithreaded if it contains any synchronized code. If all server methods are run on a single thread and that thread is blocked in a method that is waiting for some condition to change then does that mean that no other methods can be invoked on the server? If so, then it will be impossible for any methods to be invoked remotely and do anything that may change the condition that is blocking the method that holds the object lock. The ambiguity about whether or not a method dispatched to the server will run in a separate thread present a problem for URLyBird. If it is the case that all server methods are invoked on the same thread then I must implement a multi-threaded server, probably on a thread per client basis. However, this would add a considerable amount of complexity to the code and testing has shown that it is unnecessary. My tests suggest that the implementation of RMI that I tested against creates multiple threads on the server, but is it safe to assume that all RMI implementations will do the same? The question is this: Is it the case that a remote object implementation with synchronized methods must implement some form of multi-threading just in case the RMI runtime invokes all remote methods on the same thread? Any help will be much appreciated.
Hi Glenn, Hmmm interesting. I had considered the implications of: [*]Two calls to a method from one client may be run in different threads. [*]Two calls to a method from different clients may run in the same thread if the thread is not currently in use. But I had not considered the case where an RMI JVM only ever allocate one thread to service all possible clients. I think you are right though: I think such a scenario coud theoretically be allowed by the specification. Having said that: I dont think I would spend much (if any) time on it. Explicitly creating your own threads to handle this unlikely event may be overkill. Regards, Andrew [ July 09, 2003: Message edited by: Andrew Monkhouse ]
I think that any RMI server that only allows a single thread for all clients is going to be a pretty crappy server, and we just have to assume that people will run on a JVM which is not excessively crappy. Well, it's not just an assumption - you can test it yourself for a specific platform and JDK at least, and document that. But you can't really worry about all possible implementations. A comparable situation is garbage collection. The language and JVM specifications do not require that garbage collection ever succeed in freeing up memory. It's possible to write a legal JVM implementation in which GC does nothing. But in general, no respectable JVM would fail to have some sort of effective garbage collection, because if they didn't, no one would use that JVM. So generally we just assume that GC will work OK, unless/until we learn otherwise from testing. Back to RMI threading - I think the reason the RMI spec is written the way it is, is to give implementors some freedom. A common solution would be to have RMI requests serviced by a thread pool of some sort. If you do this, most clients will probably have their requests serviced by different threads - but some will get a thread that is being reused after it was previously returned to the pool. The implementors don't want to have to worry about making sure each client gets a different thread - that's too much extra tracking. They just make sure that each client gets a thread when it needs it, unless the system is just too busy right then. So the RMI spec is intentionally vague on threading issues, to allow implementors the freedom to do what they think is best. We just have to trust that "what they think is best" isn't complete crap.