How do I stop an RMI client? - java

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.

Related

How can I make a method execute when any main has completed using the java object?

I have a Java object that is a client in a RMI model and the RMI server implements a locking mechanism that only allows access from one client at a time. In order for the server to be made available for a new client, the existing client must remove its lock by calling a disconnect() method before its thread dies.
The issue I'm having is that if the client doesn't call disconnect(), the server will never free up.
Is it possible to enforce that whenever ANY main making use of the client has finished running, it calls disconnect() WITHOUT specifying so in the main?
I read about the finalize() method which is called during garbage collection, but from my understanding it is extremely unreliable.

Are java RMI remote objects (server) singleton?

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

Java RMI: Implement a time out in the client code

I have a Java RMI system. The situation is typical: the client invokes a method of the server.
The client has an internal timer, so if the server doesn't finish in due time (the time is specified in the client), then the client must do something else.
So, the client must wait for the server to finish its job for a specific time and in case the server didn't finish do something else (it doesn't matter what). How can I do this?
I don't care about connection timeouts and so on, assume that the server and client are connected through RMI and everything it's fine, only that the server's job can be computationally intensive and can require some time.
thanks a lot!
Make the RMI call on another thread. Have the originating thread wait a certain length of time for a response from the RMI-calling thread.
Alternatively, have the server RMI thread delegate the task to a worker thread. Return to the caller if the worker thread doesn't respond sufficiently quickly.
In general, when you want operations to timeout in Java, you are talking about one or two synchronous/asynchronous conversion layers. I've never done this with RMI, but I imagine you do something similar. Perhaps asking the participants of this discussion: ( Asynchronous Java RMI ) will be useful. Based on the points made in ( Spring Async RMI Call ), I would say you need to do the following:
Call the RMI service using separate thread(s); consider using executor service.
Expose this with a wrapper that calls through to the executor service and blocks for a finite amount of time for results; consider using Futures.
You need to set the undocumented property called (I think) sun.rmi.transport.tcp.responseTimeout at each client JVM. Value in milliseconds.

Concurrency Problem in Java

I am designing a client-server chat application in Java. This is a secure application where the messages are exchanged using cryptographic algorithms. I have one server and it can support many clients. My problem is that when one client logs on the server it works fine, but when another user logs into the system, the server starts giving me bad padding exceptions for the encrypted text.
I am not able to figure out the problem, according to my logic, when new connection request to server is made, the server creates a thread for listening to the client. Is it possible that once the instance of thread class is created, it does all the processing correctly for the first client, but not for the second client because the variables in server listener thread class already have some previous value, and thus the encrypted text is not decrypted properly?
Please advise how I can make this process more robust so that the number of clients does not affect how well the server functions.
Hi, The code is like this :
When Server Starts:
Socket in= serverSocket.accept();
Receive rlt = new Receive(in);
Thread receiveReq = new Thread(rlt);
receiveLoginReq.start();
now the Receive Thread waits for the incoming message and do the process according to message type. When more than one client is invoked, Server works fine, problem starts when one client terminates and then again tries to reconnect. Server always gives the Error in following pattern:
First time the HAsh not matched error for second client
Second time javax.crypto.BadPaddingException: Given final block not properly padded error
When this happens, I need to restart server and restart both clients, only then both clients works. but again if one client terminates connection and again tries to reconnects, the same 2 errors occurs in the same manner. and then again restart Server.
Any Advise will be highly appreciated.
Thanks
Don't share mutable data with threads. Use functional style - no object states. If you really need to share some data with the threads then use message passing.
Check that you close connections in a proper way.
You could use a real server like Jetty that is very easy to install.
I can only guess the reasons without seeing the full source code. I assume you are using CipherInput/OutputStream for your encryption. You should use separate instances of Cipher for each thread (each I/OStream). Every time you create a new connection or re-connect, run the init method of Cipher on both the client and server side and create new CipherInput/OutputStream instances.
The cryptographic objects are stateful, therefore they cannot be shared between threads. Each thread and each connection should have its separate sets of stateful objects.
Check out java.lang.ThreadLocal class.

When should I call Naming.unbind()?

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).

Categories