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).
Related
Scenario
We are developing an API that will handle around 2-3 million hits per hour in a multi-threaded environment. The server is Apache Tomcat 7.0.64.
We have a custom object with lot of data let's call it XYZDataContext. When a new request comes in we associate XYZDataContext object to the request context. One XYZDataContext object per request. We will be spawning various threads in parallel to serve that request to collect/process data from/into XYZDataContext object. Our threads that will process things in parallel need access to this XYZDataContext object and
to avoid passing around of this object everywhere in the application, to various objects/methods/threads,
we are thinking to make it a threadlocal. Threads will use data from XYZDataContext object and will also update data in this object.
When the thread finishes we are planning to merge the data from the updated XYZDataContext object in the spawned child thread into the main thread's XYZDataContext object.
My questions:
Is this a good approach?
Threadpool risks - Tomcat server will maintain a threadpool and I read that using threadlocal with thread pools is a disaster because thread is not GCed per say and is reused so the references to the threadlocal objects will not get GCed and will result in storing huge objects in memory that we don't need anymore eventually resulting into OutOfMemory issues...
UNLESS they are referenced as weak references so that get GCed immediately.
We're using Java 1.7 open JDK. I saw the source code for ThreadLocal and the although the ThreadLocalMap.Entry is a weakreference it's not associated with a ReferenceQueue, and the comment for Entry constructor says "since reference queues are not used, stale entries are guaranteed to be removed only when the table starts running out of space."
I guess this works great in case of caches but is not the best thing in our case. I would like that the threadlocal XYZDataContext object be GCed immediately. Will the ThreadLocal.remove() method be effective here?
Is there any way to enforce emptying the space in the next GC run?
This is a right scenario to use ThreadLocal objects? Or are we abusing the threadlocal concept and using it where it shouldn't be used?
My gut feeling tells me you're on the wrong path. Since you already have a central context object (one for all threads) and you want to access it from multiple threads at the same time I would go with a Singleton hosting the context object and providing threadsafe methods to access it.
Instead of manipulating multiple properties of your context object, I would strongly suggest to do all manipulations at the same time. Best would be if you pass only one object containing all the properties you want to change in your context object.
e.g
Singleton.getInstance().adjustContext(ContextAdjuster contextAdjuster)
You might also want to consider using a threadsafe queue, filling it up with ContextAdjuster objects from your threads and finally processing it in the Context's thread.
Google for things like Concurrent, Blocking and Nonblocking Queue in Java. I am sure you'll find tons of example code.
In netty, Objects processed by ChannelHandler(s) should be released by calling ReferenceCountUtil.release(). I am using customized objects in my application and documents says any object needed to be released should implement ReferenceCounted so it could be managed by netty framework.
So should we put a clean up handler at the tail of the channel pipeline to release incoming third party objects (I don't intercept outbound messages)? Did I get this idea correctly?
It depends on what the third party object is, but if it does not implement ReferenceCounted and it is reclaimed by JVM garbage collector without any problem, you don't really need to do anything.
The reason Netty expects you to release a ReferenceCounted object is because it contains something that 'must' be released immediately. (e.g. direct buffers, pooled buffers)
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'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.