EDIT : I've decided to properly setup/handle the serialUID's in the classes that are being returned from my RMI interface. This will avoid having to do any custom class loading/managing, solves my issue in a few lines and avoids a lot of headaches. Thanks for everyone's suggestions and help!
I'm currently faced with the issue of having to communicate via Java RMI to devices which may be using 2 different versions of the same JAR. I have a client side copy of each JAR (trimmed down to the necessary classes and stubs) as well. The communication between server/client happens using a single interface which hasn't changed (what has changed is the definitions & serialUID's of objects that the interface's methods return).
Ideally what I'd like to be able to do is to preload the classes from one JAR on the client side, then try to call a method on the interface retrieve an object. If the unmarshaling fails, i'd like to then try loading the classes from the other JAR and trying again.
What I've done so far:
I don't include either of my JAR's on the classpath when starting the VM. I then created a class (CustomClassLoader) which inherits from RMIClassLoaderSpi and set it as the RMI classloader using the java.rmi.server.RMIClassLoaderSpi property. In this custom loaders loadClass method I basically check if the name of the class to load matches one of the ones I'm interested in and if so I load it from a JAR, then cache the Class object for returning later.
This seems to load my interface stub and other classes in the JAR using my custom loader however when I do a:
(EmsRMIInterface)Naming.lookup(path)
to try to get my interface reference I get a ClassNotFoundException. It looks like the cast is using a different URLClassLoader and I'm not sure how to force it to use my custom one. Any suggestions/ideas on what I could do?
Caused by: java.lang.ClassNotFoundException: ems.rmi.EmsRMIInterface
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)