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.
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 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
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.
With C++ and C# experience and some little Java knowledge I'm now starting a Java+JNI (C++) project (Android, if that matters).
I have a native method, that creates some C++ class and returns a pointer to it as a Java long value (say, handle). And then other native methods called from Java code here and there, use the handle as a parameter to do some native operations on this class. C++ side does not own the object, it's Java side who does. But in the current architecture design it's hard to define who exactly owns the object and when to delete it. So it would probably be nice to make Java VM garbage collector to manage the object's lifetime somehow. The C++ class does not consume any resources, except some piece of memory, not large. So it's OK, if several such objects will not be destructed.
In C# I would probably wrap the native IntPtr handle in some managed wrapper class. And override it's finalizer to call native object's destructor when the managed wrapper is garbage collected. SafeHandle, AddMemoryPressure, etc. might be also of help here.
This is a different story with Java's finalize. The second thing you know after 'Hello world' in Java, is that using finalize is bad. Are there any other ways to accomplish this in Java? Maybe using PhantomReference?
Well let's consider the reason WHY finalize and Co are problematic: As you know there's no guarantee that the finalize will be called before the VM is shut down, which means that special cleanup code won't necessarily run (imo a bad decision, I don't see any problems to run through the finalize queue at cleanup, but well that's how it is). Also this is exactly the same situation in C#
Now your objects only consume memory, which will be cleaned up by the OS anyhow when the VM is destroyed, so the only case where finalize is problematic won't matter for you. So yes you can indeed use this variant and it'll work perfectly fine, but it may not exactly be considered a great architectural design - and as soon as you add resources to your C++ code where the OS doesn't handle the cleanup correctly you will run into problems
Also note that implementing a finalizer results in some additional overhead for the GC and means it takes two cycles to cleanup one of these objects (and whatever you do, don't ever save an object in the finalize method)
If you understand why you should avoid using Java's finalize method, you will also understand how to use it correctly. Using finalize for closing system resources (files and handles) is bad because you don't actually know when those resources will be closed and released. Using complex finalize logic is bad as your object reference can leak out and get pinned in memory again.
For your scenario, it is perfectly fine to use finalize.
using a wrapper with a finalizer is a decent solution here
but if you really don't wanna do that you can use a PhantomReference with a ReferenceQueue to clean it up (but you are going to require a separate thread to poll the queue)
So how can we achieve it using phantom reference.
Create a wrapper object for your native intPtr object. Create a
phantom reference(with a reference queue) on the wrapper object.
Create and maintain a map of phantom reference to intPtr.
Create a thread that will be monitoring the reference queue for finalized
wrapper object instances.
This thread will get the phantom reference from reference queue, lookup intPtr using phantom reference and call destructor on native int object referenced by intPtr.
While all this happening, you can go about happily using the
wrapper object in your java code.
I have some code which I am making available via RMI.
If my program terminates abnormally, I won't have called Naming.unbind(), and a reference to the object will presumably be hanging around in the RMI registry, and subsequent calls to Naming.bind() with the same name will fail.
How do I make sure that rogue references are cleared up?
There is something called Distributed Garbage Collector (DGC). It uses leases to track stale bindings and will collect them once they are not used. Set the leaseValue system property of the exporting JVM to determine when a binding expires.
Setting the value to too low would result in increased network traffic. Setting it too high will result in stale references being held too long. You can call an idempotent method after lookup on the client side just to make sure the object is live (or use something like the Weblogic smart stubs). On the server side, you can check the registry and if a binding exist either unregister it (in case it's stale), dispose the remote object and export a new one or just leave it (if it's live).