[rules-dev] ClassLoader Improvements and OSGi

Mark Proctor mproctor at codehaus.org
Sat Dec 4 17:00:34 EST 2010


On 04/12/2010 20:37, Michael Anstis wrote:
> It'd be great to learn a little more about Drools' class loading 
> strategy; where it's come from and where it is now.
>
> Can anyone explain more about Drools class loading? I can guess the 
> RETE network needs to know how to load classes declared in rules; 
> however this no doubt is the tip of an iceberg.
Initially the user would pass a classloader which would be the "parent" 
classloader that Drools would use for any classloaders it created. 
Drools would create a classloader to be able to dynamically load byte[] 
classes at runtime and we would have one of those per package namespace:
     public static class ByteArrayClassLoader extends ClassLoader {
         public ByteArrayClassLoader(final ClassLoader parent) {
             super( parent );
         }

         public Class< ? > defineClass(final String name,
                                       final byte[] bytes,
                                       final ProtectionDomain domain) {
             return defineClass( name,
                                 bytes,
                                 0,
                                 bytes.length,
                                 domain );
         }
     }

This way the user could also have custom classloaders with classes not 
in the classpath.

The problem then came that there was not resolving across packages, a 
type declaration or function in one package could not be resolved in 
another package. Thats because the current classloader, as shown above 
would only resolve against itself and the parent.

We then changed to a Composite ClassLoader. In this we subvert normal 
classloader behaviour by over-riding the loadClass method. ALL 
classloading should be via this "root" composite classloader. The 
composite has an array ClassLoaders and any class loading now resolves 
across the entire array. This means that one package can now resolve 
against another. It also means we can add multiple external 
classloaders, as needed by OSGi. Notice we pass null to the super() now, 
as we never search the parent.

We further added some classloader caching to help address performance 
issues for people tha have particularly large class paths.

http://fisheye.jboss.org/browse/JBossRules/trunk/drools-api/src/main/java/org/drools/util/CompositeClassLoader.java?r=HEAD

There is a ClassLoaderUtils class that is used to construct the 
composite classloaders and this dictates the ordering, notice it's in 
reverse order as it's LIFO priority.

http://fisheye.jboss.org/browse/JBossRules/trunk/drools-api/src/main/java/org/drools/util/ClassLoaderUtil.java?r=HEAD

There's a bit more history to it than that, but it gives you the gist. 
For a while we ended up having two parallel composite implementations, 
one for the root and one for the internal dynamic stuff, so it was a it 
messy for a while.

Mark
>
> Thanks,
>
> Mike
>
> On 4 December 2010 04:53, Mark Proctor <mproctor at codehaus.org 
> <mailto:mproctor at codehaus.org>> wrote:
>
>     I have done more cleaning up in the ClassLoader stuff.
>
>     While we added a root CompositeClassLoader recently there was still
>     another alternative composite ClassLoader implementation that was used
>     by the Packages. So we ended up with a composite CL being added to
>     another CL. Both composites had their own caching etc.
>
>     So now we have  single CompositeClassLoader, with a single point of
>     caching and slightly improve coding at detecting Drools specific
>     CLs. My
>     hope is that the code is also more efficient.
>
>     This work was done due to another OSGi requirement where each module
>     needs to add itself to the root classloader. But sometimes it was
>     returning the root CL, or sometimes the package level composite CL. So
>     now there is only one and that should no longer happen.
>
>     What this means is that any module that will have it's classes
>     resolved
>     via reflection from other modules should in their constructor or other
>     initialisation of the code do something like
>     getRootClassLoader().addClassLoader( getClass().getClassLoader() ). In
>     situations where it's a single container all modules have the same
>     classloader and the call gets ignored, as it won't re-added an
>     existing
>     CL. In the OSGi case it'll add the classloader and now classes
>     from that
>     module can be resolved in an OSGi environment.
>
>     Mark
>
>     _______________________________________________
>     rules-dev mailing list
>     rules-dev at lists.jboss.org <mailto:rules-dev at lists.jboss.org>
>     https://lists.jboss.org/mailman/listinfo/rules-dev
>
>
>
> _______________________________________________
> rules-dev mailing list
> rules-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-dev/attachments/20101204/86a6f386/attachment-0001.html 


More information about the rules-dev mailing list