I have been using java RMI for a while now but I couldn't figure out if the RMI Remote Stubs (on the server side) are singleton? The reason I ask is:
lets assume that one of the RMI implementation methods lower down in the chain of calls have a synchronized method. If for some reason the logic in the Synchronized Method is messed up (or hangs), the future RMI calls (from the client) will hang too while trying to get access to that synchronized method. This will hold true only if the RMI stubs are going to be singleton. If a new object is created on the server side at every remote call from the client, this won't be a problem because than the methods are being called from a different object and synchronized method won't be an issue anymore.
Long story short. I am trying to understand how JVM internally maintains rmi remote objects on the server side and if they are singleton. I tried many different javadocs but they don't explicitly mention this anywhere.
Any and all help is appreciated !
EDIT
Based on some questions and comments, I am refining the question: my real question is, does RMI on the server side happen to keep some kind of an object pool based on what one object you export and register ? Can you bind more than one object of the same type with the same name (somewhat simulating an object pool where RMI can give me any of the objects that I registered) or in order to have multiple instances of the same object, I will have to register them with different names
First of all, the "stub" is a client-side concept, there are no stubs on the server.
As for the remote objects themselves, the RMI system doesn't instantiate the objects for you, it's up to you to create instances and export them. You create one instance of the object, export that object, and bind it in the registry under a particular name. All calls on client stubs obtained from that same name in the registry will ultimately end up at the same object on the server.
Can you bind more than one object of the same type with the same name (somewhat simulating an object pool where RMI can give me any of the objects that I registered)
No, you can only bind one object in the registry under a given name. But the object you bind could itself be a proxy to your own object pool, for example using the Spring AOP CommonsPoolTargetSource mechanism.
RMI its based on proxy design pattern.
See what says here
A RMI Server is an application that creates a number of remote objects. An RMI Server is responsible for:
Creating an instance of the remote object (e.g. CarImpl instance = new CarImpl());
Exporting the remote object;
Binding the instance of the remote object to the RMI registry.
Stubs are not singletons, but your question is really about the server-side objects. They are not singletons either, unless you implement them that way yourself. RMI doesn't do anything about that whatsoever.
EDIT Based on some questions and comments, I am refining the question: my real question is, does RMI on the server side happen to keep some kind of an object pool based on what one object you export and register?
No.
Can you bind more than one object of the same type with the same name
No.
I will have to register them with different names
You don't have to register them at all. You need one singleton remote object bound into the Registry: consider that as a factory method for further remote objects, which are returned as results from its remote methods. For example, a remote Login object is bound in the Registry and has a single login() method that returns a remote session object, a new one per login, with its own API.
From the Java docs:
http://docs.oracle.com/javase/7/docs/platform/rmi/spec/rmi-arch3.html
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.
Yes, the server side method is synchronized. The implementation is platform-specific. You cannot assume anything else about threading. And you certainly cannot assume whether or not the remote object is a singleton.
Also, it might be useful to look at Remote Object Activitation:
http://docstore.mik.ua/orelly/java-ent/jenut/ch03_06.htm
http://docs.oracle.com/javase/7/docs/api/java/rmi/activation/package-summary.html
Related
I am currently studying how Java RMI works but I do not understand a certain aspect.
In a non-distributed multithredaded environment if methods on the same object are called simultaneously from different threads each of them will be executed on the respective thread's stack (accessing shared data is not a part of my question).
In a distributed system since a client process calls methods on the stub and the actual call is executed on the stack of the process that created the remote object how are simultaneous calls to a method handled? In other words what happens at the lets say server thread when there are two (or more) requests to execute the same method on that thread?
I thought of this question as I want to compare this to what I am used to - the executions being on different stacks.
how are simultaneous calls to a method handled?
It isn't specified. It is carefully stated in the RMI specification: "The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads."
The occult meaning of this is that you can't assume the server is single-threaded.
In other words what happens at the lets say server thread when there are two (or more) requests to execute the same method on that thread?
There can't be two or more requests to execute the method on the same thread. The question doesn't make sense. You've posited a unique 'lets say server thread' that doesn't actually exist.
There can however be two or more requests to execute the method arising from two or more concurrent clients, or two or more concurrent threads in a single client, or both, and because of the wording of the RMI Specification you can't assume a single-threaded despatching model at the server.
In the Oracle/Sun implementation it is indeed multi-threaded, ditto the IBM implementation. I'm not aware of any RMI implementation that isn't multi-threaded, and any such implementation would be basically useless.
I suppose singleton are per JVM only
but I am trying to keep them(state of singleton objects) in sync in distributed environment
And as we know Singleton have only one instance in JVM so when we get any changes in any JVM Singleton how we can update other JVM Singleton instances?
Here my focus is totally on keeping the state of objects in sync.
Have the singleton be a static field in the class
It clearly depends on what you want to be there just once (singleton). If it is data/state, you can check for a modern distributed database and how they keep the stat consistent across different instances (even eventually).
If you want a singular instance, you can use things that are unique in a computer network, like a SocketAddress (bound to a real hostname). Your "Distributed Singleton" starts up with trying to connect to that address(es) and if it proceeds it is just a delegate. If not, it can try to bind to that address - accepting connections from there, being the ONE - or just give up.
In delegate mode, all method calls to the instance are just sent via the socket to the ONE.
Being the ONE it can track who is connected and map the incoming messages to method calls and reply according to its internal state.
This is quite a scribble without any failover, redundancy etc. but it should do the job in principle.
I'd suggest you anyway to check for cluster-frameworks (like http://akka.io) that provide such things (mostly) out of the box.
I am designing an RMI based data service server for different Java clients. The clients use RMI to perform CRUD operations remotely, and I plan to use JPA for the server's ORM.
As I know some RMI requests implementation to be thread-safe, so I am planning to inject the EntityManager using #PersistenceContext. I have two questions.
Does spring make the EntityManager injected thread safe, or should I inject EntityManagerFactory and call createEntityManager when necessary?
Do I still have to make sure synchronized when method code is guaranteed to be thread safe?
According to the RMI specification
When a remote request comes in, it is immediately demarshalled into a request object
that encapsulates the method invocation. This request object, which is an instance of a
class implementing the RemoteCall interface, has a reference to the socket's output
stream. This means that, although RMI shares sockets, a socket is used only for one
remote method invocation at a time.
The thread that received the request from the socket finds the intended remote object for
the method invocation, finds the skeleton associated with that remote object, and invokes
that skeleton's dispatch( ) method. The dispatch method has the following signature:
public void dispatch(java.rmi.Remote obj,
java.rmi.server.RemoteCall call, int
opnum, long hash) throws java.lang.Exception
The skeleton's dispatch( ) method invokes the right method on the server. This is
where the code you wrote is actually executed.
The server method returns a value, which is eventually propagated back through the
socket on which the original request was received.
I think the process definition suggests many separated call stacks of our code could be created in RMI environment. therefore, RMI requires code to be Thread safe, am I right?
When you export an object via RMI, it has to deal with multiple threads, even if you just have a single client for the object. Here's why: The thread on which you create the remote object is definitely different from the thread that handles remote invocations.
So if you inject the EntityManager during the creation of the remote object, it will have been injected on a different thread than the one it is used on during a remote call. However, an EntityManager can only be used on a single thread and more specifically on the thread on which is was created. With Hibernate, for example, your EntityManager will not work unless this is the case.
So you have to use an EntityManagerFactory to create the EntityManager on demand. To minimize EntityManager creations, you could store the EntityManager in a ThreadLocal.
RMI requires code to be Thread safe, am I right?
Strange you are are asking a question that has already been answered in comments, but regardless of what you've quoted above there is a much shorter piece in the RMI Specification #3.2 that says exactly that:
"a remote object implementation needs to make sure its implementation is thread-safe."
I'm working on a project which is being revamped/modernized and it has a small RMI piece in it and unfortunately I never worked with RMI before.
One thing I am unable to figure out is why it keeps calling its custom SocketFactory constructor after I initially create a RMI client. It seems to happen like every 5 minutes I see output that the constructor is called even when there is no traffic between client and server.
So I guess there must be some way to end a client or clean it up somehow so it stops doing that but I dont know what it could be.
It sets up the RMI connection like so:
UnicastRemoteObject.exportObject(this);
TheServer rmiServer = (TheServer)Naming.lookup(s); // where s is some rmi:// url
So then I can access methods of the server and it can call methods on my client.
Once I am done with the connection, what should I do to cleanup and stop any threads for persisting?
I was checking out UnicastRemoteObject, maybe I need to use the method unexportObject?
But how is this custom SocketFactory getting called anyway, there are absolutely no references to its class name in my project, unless its some reflection in the background which is finding it by deriving the class name from the name of the client or something...
You are seeing the effect of Distributed Garbage Collection. If you're finished with the stub, just release all local references and let it be locally garbage-collected. Then DGC will stop too, and all network activity to that remote object.
I have an RMI server client relationship (each running in a different JVM), and the RMI server creates a large object and returns it to the RMI client. After this is done which JVM (server or client) owns the actual memory for that object? If the object is passed between JVMs how is that done? Does it involve a disk hit, or is there some magic that makes it super fast?
Thanks
It depends on whether this large object is a remote object -- whether it indirectly implements java.rmi.Remote and is exported -- or if it's an ordinary serializable object, in which case it is copied from one JVM to the other. If it's the former, then it always stays in the JVM that created it. If it's the later, then it's copied from one to the other when it's passed as an argument to a remote method, or returned from a call to a remote method. The copies are plain, ordinary Java objects, and subject to being garbage collected at either end according to normal rules.