On 20/08/2012 10:07 AM, GREGG WONDERLY wrote:
The point of my changes was to make it possible for arbitrary behaviors.  What you 
describe below, could be done as a "version" of the SPI.
Thanks Gregg, glad you're still participating.

That's my intent, to determine what, if anything else, is required by other SPI implementations at this moment, now that RMIClassLoader has come up for replacement. (I have literally replaced allmost all instances of it in my development env with CodebaseAccessClassLoader, including all the qa tests).

By annotating some other information about the originating classes, we could provide more information to CodebaseAccessClassLoader, there are two ways of doing so, the first would be to create a new URL scheme and handler that included it in URL strings, but this is too much like a hack. (you can include version information as part of the codebase name now, although this won't suit all environments).

The other option would be the increment the stream version, add the possiblility of annotating additional information into the stream, the stream version in use in an environment could be set as an envirionment variable.

The difficulity is of course working out the minimum information required in a modular environment, which could include OSGi or Java 9 for instance.

We could allow an additional string, that has a list of comma separated key value pairs, allowing implementors to pass additional information through the stream.

The netbeans model is interesting, it basically means you can walk the call stack, just like ObjectInputStream, although at present we choose to use the Thread context ClassLoader, which causes breakage, but walking the call stack won't.

Check out net.jini.security.Security if you need an example of stack inspection.

I need a little more time figure it out properly, then I'll come back with some further thoughts / suggestions.

Cheers,

Peter.

   The modular programming systems like OSGi and Netbeans etc., often have differing 
needs, depending on what you want to expose to "who", and those things might 
change over time, or depending on users.

Netbeans modules, in particular have a hierarchical structure based on declared dependencies.  This 
can mean that two modules might resolve a class differently, depending on what he developer 
declares.  So, it can be necessary to do some interesting things.  The Netbeans system will largely 
provide the right structure for you, so that you can use the "current class" in a 
particular module's class loader as the "parent" for proxy resolution.

Gregg Wonderly

On Aug 19, 2012, at 7:09 AM, Peter Firmstone<[email protected]>  wrote:

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.




Reply via email to