You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:19:40 UTC

[sling-org-apache-sling-commons-classloader] 13/21: SLING-1070 : Change class loading of package admin class loader to parent first, cache classes and resources in the class loader facade and reregister manager factory, if a used bundle is changed.

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.classloader-0.9.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-classloader.git

commit ce0fe406f4b477265a12ebb0cdf5f514e657802f
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Aug 4 14:03:59 2009 +0000

    SLING-1070 : Change class loading of package admin class loader to parent first, cache classes and resources in the class loader facade and reregister manager factory, if a used bundle is changed.
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/classloader@800803 13f79535-47bb-0310-9956-ffa450edef68
---
 .../commons/classloader/ClassLoaderWriter.java     | 42 ++++++++--
 .../classloader/DynamicClassLoaderManager.java     |  5 ++
 .../sling/commons/classloader/impl/Activator.java  | 54 +++++++++++--
 .../classloader/impl/BundleProxyClassLoader.java   |  2 +
 .../classloader/impl/ClassLoaderFacade.java        | 49 ++++++++----
 .../impl/DynamicClassLoaderManagerFactory.java     | 26 +++++-
 .../impl/DynamicClassLoaderManagerImpl.java        | 21 ++++-
 .../classloader/impl/PackageAdminClassLoader.java  | 92 +++++++++++++++++-----
 .../commons/classloader/impl/ClassLoadingTest.java |  8 +-
 9 files changed, 243 insertions(+), 56 deletions(-)

diff --git a/src/main/java/org/apache/sling/commons/classloader/ClassLoaderWriter.java b/src/main/java/org/apache/sling/commons/classloader/ClassLoaderWriter.java
index b39b746..82e6634 100644
--- a/src/main/java/org/apache/sling/commons/classloader/ClassLoaderWriter.java
+++ b/src/main/java/org/apache/sling/commons/classloader/ClassLoaderWriter.java
@@ -30,13 +30,45 @@ import java.io.OutputStream;
  */
 public interface ClassLoaderWriter {
 
-    OutputStream getOutputStream(String name);
+    /**
+     * Get the output stream for a class or resource handled
+     * by the underlying class loader.
+     * If the resource/class does not exists it should be created.
+     * @param path The path of the class/resource.
+     * @return The output stream.
+     */
+    OutputStream getOutputStream(String path);
 
-    InputStream getInputStream(String name) throws IOException;
+    /**
+     * Get the input stream for a class or resource handled
+     * by the underlying class loader.
+     * @param path The path of the class/resource.
+     * @return The input stream for the resource/class.
+     * @throws IOException If the resource/class does not exist.
+     */
+    InputStream getInputStream(String path) throws IOException;
 
-    long getLastModified(String name);
+    /**
+     * Return the last modified for the class or resource.
+     * @param path The path of the class/resource.
+     * @return The last modified information or <code>-1</code> if
+     *         the information can't be detected.
+     */
+    long getLastModified(String path);
 
-    boolean delete(String name);
+    /**
+     * Delete the class/resource
+     * @param path The path of the class/resource.
+     * @return <code>true</code> if the resource exists and could be deleted,
+     *     <code>false</code> otherwise.
+     */
+    boolean delete(String path);
 
-    boolean rename(String oldName, String newName);
+    /**
+     * Rename a class/resource.
+     * @param oldPath The path of the class/resource.
+     * @param newPath The new path.
+     * @return <code>true</code> if the renaming has been successful.
+     */
+    boolean rename(String oldPath, String newPath);
 }
diff --git a/src/main/java/org/apache/sling/commons/classloader/DynamicClassLoaderManager.java b/src/main/java/org/apache/sling/commons/classloader/DynamicClassLoaderManager.java
index ff23e78..25aae5b 100644
--- a/src/main/java/org/apache/sling/commons/classloader/DynamicClassLoaderManager.java
+++ b/src/main/java/org/apache/sling/commons/classloader/DynamicClassLoaderManager.java
@@ -24,6 +24,11 @@ package org.apache.sling.commons.classloader;
  * It provides a class loader that can be used by
  * bundles requiring access to all publically available
  * classes.
+ *
+ * The default implementation uses the package admin
+ * service to load classes and resources. The search
+ * path can be extended by providing
+ * {@link DynamicClassLoaderProvider}s.
  */
 public interface DynamicClassLoaderManager {
 
diff --git a/src/main/java/org/apache/sling/commons/classloader/impl/Activator.java b/src/main/java/org/apache/sling/commons/classloader/impl/Activator.java
index 1ca885e..33ea4f5 100644
--- a/src/main/java/org/apache/sling/commons/classloader/impl/Activator.java
+++ b/src/main/java/org/apache/sling/commons/classloader/impl/Activator.java
@@ -21,17 +21,21 @@ package org.apache.sling.commons.classloader.impl;
 import java.util.Hashtable;
 
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
-import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.SynchronousBundleListener;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
  * This activator registers the dynamic class loader manager.
+ * It listens for bundle events and reregisters the class loader manager
+ * if a bundle event for a used bundle occurs.
  */
-public class Activator implements BundleActivator {
+public class Activator implements SynchronousBundleListener, BundleListener {
 
     /** Package admin service name */
     private static String PACKAGE_ADMIN_NAME = PackageAdmin.class.getName();
@@ -45,26 +49,39 @@ public class Activator implements BundleActivator {
     /** The dynamic class loader service factory. */
     private DynamicClassLoaderManagerFactory service;
 
+    /** The bundle context. */
+    private BundleContext bundleContext;
+
     /**
      * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
      */
-    public void start(BundleContext context) throws Exception {
-        this.packageAdminTracker = new ServiceTracker(context, PACKAGE_ADMIN_NAME, null);
+    public void start(BundleContext context) {
+        this.bundleContext = context;
+
+        this.packageAdminTracker = new ServiceTracker(this.bundleContext, PACKAGE_ADMIN_NAME, null);
         this.packageAdminTracker.open();
 
         // register service
+        this.registerManagerFactory();
+        this.bundleContext.addBundleListener(this);
+    }
+
+    /**
+     * Register the dynamic class loader manager factory.
+     */
+    protected void registerManagerFactory() {
         final Hashtable<String, String> props = new Hashtable<String, String>();
         props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Dynamic Class Loader Service");
         props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
-        this.service = new DynamicClassLoaderManagerFactory(context,
+        this.service = new DynamicClassLoaderManagerFactory(this.bundleContext,
                 (PackageAdmin)this.packageAdminTracker.getService());
-        this.serviceReg = context.registerService(new String[] {DynamicClassLoaderManager.class.getName()}, service, props);
+        this.serviceReg = this.bundleContext.registerService(new String[] {DynamicClassLoaderManager.class.getName()}, service, props);
     }
 
     /**
-     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+     * Unregister the dynamic class loader manager factory.
      */
-    public void stop(BundleContext context) throws Exception {
+    protected void unregisterManagerFactory() {
         if ( this.serviceReg != null ) {
             this.serviceReg.unregister();
             this.serviceReg = null;
@@ -72,9 +89,30 @@ public class Activator implements BundleActivator {
         if ( this.service != null ) {
             this.service = null;
         }
+    }
+
+    /**
+     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+     */
+    public void stop(BundleContext context) {
+        context.removeBundleListener(this);
+        this.unregisterManagerFactory();
         if ( this.packageAdminTracker != null ) {
             this.packageAdminTracker.close();
             this.packageAdminTracker = null;
         }
+        this.bundleContext = null;
+    }
+
+    /**
+     * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
+     */
+    public void bundleChanged(BundleEvent event) {
+        final long bundleId = event.getBundle().getBundleId();
+        boolean needsUpdate = this.service.isBundleUsed(bundleId);
+        if ( needsUpdate ) {
+            this.unregisterManagerFactory();
+            this.registerManagerFactory();
+        }
     }
 }
diff --git a/src/main/java/org/apache/sling/commons/classloader/impl/BundleProxyClassLoader.java b/src/main/java/org/apache/sling/commons/classloader/impl/BundleProxyClassLoader.java
index 75cb21d..efef5db 100644
--- a/src/main/java/org/apache/sling/commons/classloader/impl/BundleProxyClassLoader.java
+++ b/src/main/java/org/apache/sling/commons/classloader/impl/BundleProxyClassLoader.java
@@ -27,6 +27,8 @@ import org.osgi.framework.Bundle;
 /**
  * The <code>BundleProxyClassLoader</code> is a class loader
  * delegating to a bundle.
+ * We don't need to cache as the {@link ClassLoaderFacade} is
+ * already doing this.
  */
 public class BundleProxyClassLoader extends ClassLoader {
 
diff --git a/src/main/java/org/apache/sling/commons/classloader/impl/ClassLoaderFacade.java b/src/main/java/org/apache/sling/commons/classloader/impl/ClassLoaderFacade.java
index e852bd8..d080d67 100644
--- a/src/main/java/org/apache/sling/commons/classloader/impl/ClassLoaderFacade.java
+++ b/src/main/java/org/apache/sling/commons/classloader/impl/ClassLoaderFacade.java
@@ -19,19 +19,30 @@
 package org.apache.sling.commons.classloader.impl;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URL;
 import java.util.Enumeration;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 
 /**
  * The <code>ClassLoaderFacade</code> is a facade
  * for the dynamic class loading.
+ * This class loader is returned to the clients of the
+ * dynamic class loader manager.
+ * This class loader delegates to other class loaders
+ * but caches its result for performance.
  */
 public class ClassLoaderFacade extends ClassLoader {
 
     private final DynamicClassLoaderManagerImpl manager;
 
+    /** A cache for resolved classes. */
+    private Map<String, Class<?>> classCache = new ConcurrentHashMap<String, Class<?>>();
+
+    /** A cache for resolved urls. */
+    private Map<String, URL> urlCache = new ConcurrentHashMap<String, URL>();
+
     public ClassLoaderFacade(final DynamicClassLoaderManagerImpl manager) {
         this.manager = manager;
     }
@@ -40,11 +51,19 @@ public class ClassLoaderFacade extends ClassLoader {
      * @see java.lang.ClassLoader#getResource(java.lang.String)
      */
     public URL getResource(String name) {
+        if ( !this.manager.isActive() ) {
+            throw new RuntimeException("Dynamic class loader has already been deactivated.");
+        }
+        final URL cachedURL = urlCache.get(name);
+        if ( cachedURL != null ) {
+            return cachedURL;
+        }
         final ClassLoader[] loaders = manager.getDynamicClassLoaders();
         for(final ClassLoader cl : loaders) {
             if ( cl != null ) {
                 final URL u = cl.getResource(name);
                 if ( u != null ) {
+                    urlCache.put(name, u);
                     return u;
                 }
             }
@@ -53,25 +72,12 @@ public class ClassLoaderFacade extends ClassLoader {
     }
 
     /**
-     * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
-     */
-    public InputStream getResourceAsStream(String name) {
-        final ClassLoader[] loaders = manager.getDynamicClassLoaders();
-        for(final ClassLoader cl : loaders) {
-            if ( cl != null ) {
-                final InputStream i = cl.getResourceAsStream(name);
-                if ( i != null ) {
-                    return i;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
      * @see java.lang.ClassLoader#getResources(java.lang.String)
      */
     public Enumeration<URL> getResources(String name) throws IOException {
+        if ( !this.manager.isActive() ) {
+            throw new RuntimeException("Dynamic class loader has already been deactivated.");
+        }
         final ClassLoader[] loaders = manager.getDynamicClassLoaders();
         for(final ClassLoader cl : loaders) {
             if ( cl != null ) {
@@ -88,13 +94,22 @@ public class ClassLoaderFacade extends ClassLoader {
      * @see java.lang.ClassLoader#loadClass(java.lang.String)
      */
     public Class<?> loadClass(String name) throws ClassNotFoundException {
+        if ( !this.manager.isActive() ) {
+            throw new RuntimeException("Dynamic class loader has already been deactivated.");
+        }
+        final Class<?> cachedClass = this.classCache.get(name);
+        if ( cachedClass != null ) {
+            return cachedClass;
+        }
         final ClassLoader[] loaders = manager.getDynamicClassLoaders();
         for(final ClassLoader cl : loaders) {
             if ( cl != null ) {
                 try {
                     final Class<?> c = cl.loadClass(name);
+                    this.classCache.put(name, c);
                     return c;
                 } catch (Exception cnfe) {
+                    cnfe.printStackTrace();
                     // we just ignore this and try the next class loader
                 }
             }
diff --git a/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerFactory.java b/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerFactory.java
index cad3a05..3a257d2 100644
--- a/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerFactory.java
+++ b/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerFactory.java
@@ -16,6 +16,10 @@
  */
 package org.apache.sling.commons.classloader.impl;
 
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceFactory;
@@ -34,6 +38,8 @@ public class DynamicClassLoaderManagerFactory
     /** The bundle context. */
     private final BundleContext context;
 
+    private final Set<Long> usedBundles = Collections.synchronizedSet(new HashSet<Long>());
+
     /**
      * Create a new service instance
      * @param ctx The bundle context.
@@ -50,7 +56,7 @@ public class DynamicClassLoaderManagerFactory
      */
     public Object getService(final Bundle bundle,
                              final ServiceRegistration registration) {
-        return new DynamicClassLoaderManagerImpl(this.context, this.pckAdmin, new BundleProxyClassLoader(bundle));
+        return new DynamicClassLoaderManagerImpl(this.context, this.pckAdmin, new BundleProxyClassLoader(bundle), this);
     }
 
     /**
@@ -63,4 +69,22 @@ public class DynamicClassLoaderManagerFactory
             ((DynamicClassLoaderManagerImpl)service).deactivate();
         }
     }
+
+    /**
+     * Check if a bundle has been used for class loading.
+     * @param bundleId The bundle id.
+     * @return <code>true</code> if the bundle has been used.
+     */
+    public boolean isBundleUsed(final long bundleId) {
+        return usedBundles.contains(bundleId);
+    }
+
+    /**
+     * Notify that a bundle is used as a source for class loading.
+     * @param bundle The bundle.
+     */
+    public void addUsedBundle(final Bundle bundle) {
+        final long id = bundle.getBundleId();
+        this.usedBundles.add(id);
+    }
 }
diff --git a/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerImpl.java b/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerImpl.java
index 2e5c6e1..2388b5b 100644
--- a/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerImpl.java
+++ b/src/main/java/org/apache/sling/commons/classloader/impl/DynamicClassLoaderManagerImpl.java
@@ -44,10 +44,15 @@ public class DynamicClassLoaderManagerImpl
     /** The bundle context. */
     private final BundleContext context;
 
+    /** The cached chain of class loaders. */
     private ClassLoader[] cache;
 
+    /** Needs the cache an update? */
     private boolean updateCache = false;
 
+    /** Is this service still active? */
+    private boolean active = true;
+
     /**
      * Create a new service instance
      * @param ctx The bundle context of the class loader bundle
@@ -56,10 +61,11 @@ public class DynamicClassLoaderManagerImpl
      */
     public DynamicClassLoaderManagerImpl(final BundleContext ctx,
             final PackageAdmin pckAdmin,
-            final ClassLoader parent) {
+            final ClassLoader parent,
+            final DynamicClassLoaderManagerFactory factory) {
         super(ctx, DynamicClassLoaderProvider.class.getName(), null);
         this.context = ctx;
-        this.pckAdminCL = new PackageAdminClassLoader(pckAdmin, parent);
+        this.pckAdminCL = new PackageAdminClassLoader(pckAdmin, parent, factory);
         this.cache = new ClassLoader[] {this.pckAdminCL};
         this.open();
         this.facade = new ClassLoaderFacade(this);
@@ -85,8 +91,7 @@ public class DynamicClassLoaderManagerImpl
             final ServiceReference[] refs = this.getServiceReferences();
             final ClassLoader[] loaders = new ClassLoader[1 + refs.length];
             Arrays.sort(refs, ServiceReferenceComparator.INSTANCE);
-            loaders[0] = this.pckAdminCL;
-            int index = 1;
+            int index = 0;
             for(final ServiceReference ref : refs) {
                 final DynamicClassLoaderProvider provider = (DynamicClassLoaderProvider)this.getService(ref);
                 if ( provider != null ) {
@@ -94,6 +99,7 @@ public class DynamicClassLoaderManagerImpl
                 }
                 index++;
             }
+            loaders[index] = this.pckAdminCL;
             // and now use new array
             this.cache = loaders;
             this.updateCache = false;
@@ -104,9 +110,16 @@ public class DynamicClassLoaderManagerImpl
      * Deactivate this service.
      */
     public void deactivate() {
+        this.active = false;
         this.close();
     }
 
+    /**
+     * Check if this service is still active.
+     */
+    public boolean isActive() {
+        return this.active;
+    }
 
     /**
      * @see org.apache.sling.commons.classloader.DynamicClassLoaderManager#getDynamicClassLoader()
diff --git a/src/main/java/org/apache/sling/commons/classloader/impl/PackageAdminClassLoader.java b/src/main/java/org/apache/sling/commons/classloader/impl/PackageAdminClassLoader.java
index dc98f88..f27bc8d 100644
--- a/src/main/java/org/apache/sling/commons/classloader/impl/PackageAdminClassLoader.java
+++ b/src/main/java/org/apache/sling/commons/classloader/impl/PackageAdminClassLoader.java
@@ -27,28 +27,52 @@ import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.packageadmin.PackageAdmin;
 
 /**
- * The <code>PackageAdminClassLoader</code>
+ * The <code>PackageAdminClassLoader</code> loads
+ * classes and resources through the package admin service.
  */
 class PackageAdminClassLoader extends ClassLoader {
 
+    /** The package admin service. */
     private final PackageAdmin packageAdmin;
 
-    public PackageAdminClassLoader(final PackageAdmin pckAdmin, final ClassLoader parent) {
+    /** The manager factory. */
+    private final DynamicClassLoaderManagerFactory factory;
+
+    public PackageAdminClassLoader(final PackageAdmin pckAdmin,
+                                   final ClassLoader parent,
+                                   final DynamicClassLoaderManagerFactory factory) {
         super(parent);
         this.packageAdmin = pckAdmin;
+        this.factory = factory;
     }
 
+    /**
+     * Find the bundle for a given package.
+     * @param pckName The package name.
+     * @return The bundle or <code>null</code>
+     */
     private Bundle findBundleForPackage(final String pckName) {
         final ExportedPackage exportedPackage = this.packageAdmin.getExportedPackage(pckName);
-        return (exportedPackage == null ? null : exportedPackage.getExportingBundle());
+        final Bundle bundle = (exportedPackage == null ? null : exportedPackage.getExportingBundle());
+        return bundle;
     }
 
+    /**
+     * Return the package from a resource.
+     * @param resource The resource path.
+     * @return The package name.
+     */
     private String getPackageFromResource(final String resource) {
         final int lastSlash = resource.lastIndexOf('/');
         final String pckName = (lastSlash == -1 ? "" : resource.substring(0, lastSlash).replace('/', '.'));
         return pckName;
     }
 
+    /**
+     * Return the package from a class.
+     * @param resource The class name.
+     * @return The package name.
+     */
     private String getPackageFromClassName(final String name) {
         final int lastDot = name.lastIndexOf('.');
         final String pckName = (lastDot == -1 ? "" : name.substring(0, lastDot));
@@ -60,43 +84,73 @@ class PackageAdminClassLoader extends ClassLoader {
      */
     @SuppressWarnings("unchecked")
     public Enumeration<URL> getResources(String name) throws IOException {
-        final Bundle bundle = this.findBundleForPackage(getPackageFromResource(name));
-        if ( bundle == null ) {
-            return super.getResources(name);
+        Enumeration<URL> e = super.getResources(name);
+        if ( e == null || !e.hasMoreElements() ) {
+            final Bundle bundle = this.findBundleForPackage(getPackageFromResource(name));
+            if ( bundle != null ) {
+                e = bundle.getResources(name);
+                if ( e != null && e.hasMoreElements() ) {
+                    this.factory.addUsedBundle(bundle);
+                }
+            }
         }
-        return bundle.getResources(name);
+        return e;
     }
 
     /**
      * @see java.lang.ClassLoader#findResource(java.lang.String)
      */
     public URL findResource(String name) {
-        final Bundle bundle = this.findBundleForPackage(getPackageFromResource(name));
-        if ( bundle == null ) {
-            return super.findResource(name);
+        URL url = super.findResource(name);
+        if ( url == null ) {
+            final Bundle bundle = this.findBundleForPackage(getPackageFromResource(name));
+            if ( bundle != null ) {
+                url = bundle.getResource(name);
+                if ( url != null ) {
+                    this.factory.addUsedBundle(bundle);
+                }
+            }
         }
-        return bundle.getResource(name);
+        return url;
     }
 
     /**
      * @see java.lang.ClassLoader#findClass(java.lang.String)
      */
     public Class<?> findClass(String name) throws ClassNotFoundException {
-        final Bundle bundle = this.findBundleForPackage(getPackageFromClassName(name));
-        if ( bundle == null ) {
-            return super.findClass(name);
+        Class<?> clazz = null;
+        try {
+            clazz = super.findClass(name);
+        } catch (ClassNotFoundException cnfe) {
+            final Bundle bundle = this.findBundleForPackage(getPackageFromClassName(name));
+            if ( bundle != null ) {
+                clazz = bundle.loadClass(name);
+                this.factory.addUsedBundle(bundle);
+            }
         }
-        return bundle.loadClass(name);
+        if ( clazz == null ) {
+            throw new ClassNotFoundException("Class not found " + name);
+        }
+        return clazz;
     }
 
     /**
      * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
      */
     protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-        final Bundle bundle = this.findBundleForPackage(getPackageFromClassName(name));
-        if ( bundle == null ) {
-            return super.loadClass(name, resolve);
+        Class<?> clazz = null;
+        try {
+            clazz = super.loadClass(name, resolve);
+        } catch (ClassNotFoundException cnfe) {
+            final Bundle bundle = this.findBundleForPackage(getPackageFromClassName(name));
+            if ( bundle != null ) {
+                clazz = bundle.loadClass(name);
+                this.factory.addUsedBundle(bundle);
+            }
+        }
+        if ( clazz == null ) {
+            throw new ClassNotFoundException("Class not found " + name);
         }
-        return bundle.loadClass(name);
+        return clazz;
     }
 }
diff --git a/src/test/java/org/apache/sling/commons/classloader/impl/ClassLoadingTest.java b/src/test/java/org/apache/sling/commons/classloader/impl/ClassLoadingTest.java
index e08be6e..e60256f 100644
--- a/src/test/java/org/apache/sling/commons/classloader/impl/ClassLoadingTest.java
+++ b/src/test/java/org/apache/sling/commons/classloader/impl/ClassLoadingTest.java
@@ -61,6 +61,8 @@ public class ClassLoadingTest {
             will(returnValue(ep));
             allowing(ep).getExportingBundle();
             will(returnValue(bundle));
+            allowing(bundle).getBundleId();
+            will(returnValue(2L));
             one(bundle).loadClass("org.apache.sling.test.A"); inSequence(sequence);
             will(returnValue(java.util.Map.class));
             one(bundle).loadClass("org.apache.sling.test.A"); inSequence(sequence);
@@ -68,13 +70,15 @@ public class ClassLoadingTest {
             one(bundle).loadClass("org.apache.sling.test.A"); inSequence(sequence);
             will(returnValue(java.util.ArrayList.class));
         }});
-        DynamicClassLoaderManagerImpl manager = new DynamicClassLoaderManagerImpl(bundleContext, packageAdmin, null);
+        DynamicClassLoaderManagerImpl manager = new DynamicClassLoaderManagerImpl(bundleContext, packageAdmin, null,
+            new DynamicClassLoaderManagerFactory(bundleContext, packageAdmin));
         final ClassLoader cl = manager.getDynamicClassLoader();
         final Class c1 = cl.loadClass("org.apache.sling.test.A");
         Assert.assertEquals("java.util.Map", c1.getName());
         final Class c2 = cl.loadClass("org.apache.sling.test.A");
         Assert.assertEquals("java.util.Map", c2.getName());
+        // as we cache the result, we still get the map!
         final Class c3 = cl.loadClass("org.apache.sling.test.A");
-        Assert.assertEquals("java.util.ArrayList", c3.getName());
+        Assert.assertEquals("java.util.Map", c3.getName());
     }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.