As you know Gregg's contributed his CodebaseAccessClassLoader
alternative to RMIClassLoader.
I figure we need to review MarshalInputStream and MarshalOutputStream, a
final interface for CodebaseAccessClassLoader and expected behaviour of
Class loading.
I'm also considering class loading for classes other than preferred.
You might have other ideas and opinions, please speak up.
How do we find a suitable parent class loader?
1. In a modular system, ClassLoaders don't necessarily follow a tree
hierarchy.
2. If the class belongs to a smart proxy, the parent ClassLoader is
the ClassLoader that contains the Service API.
1. The smart proxy may contain several classes.
2. Smart proxy classes should generally be preferred.
3. If we know the name of the service API interface, we can find the
parent ClassLoader in any system.
1. Annotate all smart proxy classes with the Service API
interface name (in addition to the codebase annotation).
2. Only annotate proxy classes with the proxy Codebase annotation.
3. During marshaling annotate the stream with the Service API
interface name and whether the class is preferred (this
removes the need to download the preferred list from
codebase URL to confirm if the class is preferred or not.
4. During unmarshalling, walk the call stack, find the first
non system ClassLoader and call findClass(String name), keep
traversing the stack until the Service API class is found.
5. The ClassLoader of the Service API is the parent
ClassLoader, this will work as expected in any modular system.
4. Having found the parent ClassLoader we can now lookup our Map to
find if a PreferredClassLoader has already been assigned to the
unmarshaling object class. This eliminates the need to use the
problematic Thread context ClassLoader, which may not be set or
may be set incorrectly.
Lacking codebase annotations, ObjectInputStream usually just tries to
resolve classes using the first non null ClassLoader in the call stack
(little more to it than that see the spec for details). Standard
serialisation doesn't play well with OSGi, in fact exceptions are
commonplace during deserialisation with OSGi, there is an easy way to
solve this, also annotate the package version, with this information, we
can find the correct classloader in a system where more than one
ClassLoader may contain different versions of the same classes. In a
system where only one version of a package can be found and this package
uses a different version, we'll have to accept it, or provide another
way for the client to resolve the package, this needs to be a standard
interface that can be implemented at the client (or server for objects
traveling the other way). Then maven, osgi or some other means can be
used to resolve the missing dependency.
Thoughts?
Cheers,
Peter.