You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2014/05/09 09:03:19 UTC

svn commit: r1593493 [22/24] - in /river/jtsk/skunk/qa_refactor/trunk: qa/ qa/src/com/sun/jini/test/impl/end2end/jssewrapper/ qa/src/com/sun/jini/test/impl/joinmanager/ qa/src/com/sun/jini/test/impl/mahalo/ qa/src/com/sun/jini/test/impl/outrigger/match...

Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/ClassLoading.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/ClassLoading.java?rev=1593493&r1=1593492&r2=1593493&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/ClassLoading.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/ClassLoading.java Fri May  9 07:03:18 2014
@@ -1,637 +1,637 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.jini.loader;
-
-import au.net.zeus.collection.RC;
-import au.net.zeus.collection.Ref;
-import au.net.zeus.collection.Referrer;
-import java.lang.ref.SoftReference;
-import java.net.MalformedURLException;
-import java.rmi.server.RMIClassLoader;
-import java.rmi.server.RMIClassLoaderSpi;
-import java.security.AccessController;
-import java.security.Guard;
-import java.security.PrivilegedAction;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.WeakHashMap;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import net.jini.security.Security;
-import org.apache.river.impl.thread.NamedThreadFactory;
-
-/**
- * Provides static methods for loading classes using {@link
- * RMIClassLoaderSpi} with optional verification that the codebase URIs
- * used to load classes provide content integrity (see {@link
- * Security#verifyCodebaseIntegrity
- * Security.verifyCodebaseIntegrity}).
- * <p>
- * Traditionally a class extending {@link RMIClassLoaderSpi} is determined by setting
- * the system property "java.rmi.server.RMIClassLoaderSpi", or alternatively,
- * {@link RMIClassLoaderSpi} may also be defined by {@link RMIClassLoader}
- * using a provider visible to the {@link ClassLoader} returned by 
- * {@link ClassLoader#getSystemClassLoader} with {@link ServiceLoader}.
- * </p><p>
- * As explained in River-336 this isn't always practical for IDE's or other 
- * frameworks.  To solve River-336, ClassLoading now uses {@link ServiceLoader}
- * to determine a {@link RMIClassLoaderSpi} provider, however unlike 
- * {@link RMIClassLoader}, by default it uses ClassLoading's {@link ClassLoader#getResources} 
- * instance to find providers.
- * </p><p>
- * To define a new RMIClassLoaderSpi for River to utilize, create a file in
- * your providers jar file called:
- * </p><p>
- * META-INF/services/java.rmi.server.RMIClassLoaderSpi
- * </p><p>
- * This file should contain a single line with the fully qualified name of
- * your RMIClassLoaderSpi implementation.
- * </p><p>
- * ClassLoading will iterate through all RMIClassLoaderSpi implementations found
- * until it finds one defined by the system property:
- * </p><p>
- * System.getProperty("net.jini.loader.ClassLoading.provider");
- * </p><p>
- * If this System property is not defined, ClassLoading will load 
- * <code>net.jini.loader.pref.PreferredClassProvider</code>, alternatively
- * <code>java.rmi.server.RMIClassLoader</code> delegates all calls to {@link
- * RMIClassLoader}.
- * </p><p>
- * If a provider is not found, it will not be updated.
- * </p><p>
- * <h1>History</h1>
- * <p>Gregg Wonderly originally reported River-336 and provided a patch
- * containing a new CodebaseAccessClassLoader to replace {@link RMIClassLoader}, 
- * later Sim Isjkes created RiverClassLoader that utilized ServiceLoader.
- * Both implementations contained methods identical to {@link RMIClassLoaderSpi},
- * however new implementations were required to extend new provider 
- * implementations, creating a compatibility issue with existing implementations
- * extending {@link RMIClassLoaderSpi}.  For backward compatibility with existing
- * implementations, {@link RMIClassLoaderSpi} has been retained as the provider,
- * avoiding the need to recompile client code.  The abilities of both
- * implementations, to use ServiceLoader, or to define a provider using a method
- * call have been retained, with the restriction that implementations are to be
- * obtained via ServiceLoader.
- * </p><p>
- * Instead, all that is required for utilization of existing service provider
- * {@link RMIClassLoaderSpi} implementations is to set the system property
- * "net.jini.loader.ClassLoading.provider".
- * </p>
- * @author Sun Microsystems, Inc.
- * @since 2.0
- **/
-public final class ClassLoading {
-    private final static Logger logger = Logger.getLogger(ClassLoading.class.getName());
-    private static volatile RMIClassLoaderSpi provider;
-    private static final Object lock = new Object();
-    private static final Guard permission = new RuntimePermission("setFactory");
-    
-    static {
-        provider(null, ClassLoading.class.getClassLoader());
-    }
-    
-    /**
-     * The current RMIClassLoaderSpi provider in use by ClassLoading.
-     * 
-     * @return currently installed Provider, may be null.
-     * @throws SecurityException if caller doesn't have RuntimePermission "getFactory"
-     */
-    public static RMIClassLoaderSpi getProvider(){
-        permission.checkGuard(null);
-        return provider;
-    }
-    
-    private static boolean provider(
-            final String providerName, 
-            final ClassLoader providerLoader)
-    {
-        RMIClassLoaderSpi newProvider = AccessController.doPrivileged(
-        new PrivilegedAction<RMIClassLoaderSpi>(){
-            @Override
-            public RMIClassLoaderSpi run() {
-                String name = providerName;
-                if (name == null){
-                    name = System.getProperty(
-                            "net.jini.loader.ClassLoading.provider");
-                    if (name == null) {
-                        name = "net.jini.loader.pref.PreferredClassProvider";
-                    } else if ("java.rmi.server.RMIClassLoader".equals(name)){
-                        return null;
-                    }
-                }
-                ServiceLoader<RMIClassLoaderSpi> loader 
-                   = ServiceLoader.load(RMIClassLoaderSpi.class, providerLoader);
-                Iterator<RMIClassLoaderSpi> iter = loader.iterator();
-                RMIClassLoaderSpi spi;
-                while ( iter.hasNext() ) {
-                    try {
-                        spi = iter.next();
-                        if (spi != null) {
-                            if (!name.equals(spi.getClass().getName()))
-                                continue;
-                            logger.log(Level.CONFIG, "loaded: {0}", name);
-                            return spi;
-                        }
-                    } catch (Exception e) {
-                        logger.log( 
-                                Level.CONFIG, 
-                                "error loading RMIClassLoaderSpi: {0}",
-                                new Object[]{e}
-                        );
-                    }
-                }
-                logger.log(Level.CONFIG, "uable to find {0}" , name);
-                return null;
-            }
-        });
-        if (newProvider != null) {
-            provider = newProvider;
-            return true;
-        } else if (providerName == null) {
-            provider = null;
-            logger.log(Level.CONFIG, "loaded: java.rmi.server.RMIClassLoader");
-        }
-        return false;
-    }
-    
-    /**
-     * Installs a new RMIClassLoaderSpi provider with the ClassLoader 
-     * provided.
-     * 
-     * @param providerName fully defined class name of the provider, if null,
-     * a new provider instance will be determined by system properties.
-     * @param providerLoader The class loader to be used to load 
-     * provider-configuration files and provider classes, or null if the 
-     * system class loader (or, failing that, the bootstrap class loader) 
-     * is to be used.
-     * @return true if successful.
-     * @throws SecurityException if caller doesn't have RuntimePermission "getFactory"
-     */
-    public static boolean installNewProvider(
-            String providerName, 
-            ClassLoader providerLoader)
-    {
-        permission.checkGuard(null);
-        synchronized (lock){
-            return provider(providerName, providerLoader);
-        }
-    }
-    
-    /**
-     * loaderMap contains a list of single threaded ExecutorService's for
-     * each ClassLoader, used for loading classes and proxies to avoid 
-     * ClassLoader lock contention. An Entry is removed if the ClassLoader
-     * becomes weakly reachable, or the ExecutorService hasn't been used
-     * recently.
-     */
-    private static final ConcurrentMap<ClassLoader,ExecutorService> loaderMap 
-            = RC.concurrentMap(
-                new ConcurrentHashMap<Referrer<ClassLoader>,Referrer<ExecutorService>>(),
-                Ref.WEAK_IDENTITY,
-                Ref.TIME,
-                10000L,
-                10000L
-            );
-
-    /**
-     * per-thread cache (weakly) mapping verifierLoader values to
-     * (soft) sets of codebase values that have been verified (to
-     * provide content integrity) with the verifierLoader value
-     **/
-    private static final ThreadLocal perThreadCache = new ThreadLocal() {
-	protected Object initialValue() { return new WeakHashMap(); }
-    };
-    
-        /**
-     * Returns a class loader that loads classes from the given codebase
-     * RFC3986 compliant URI path.
-     *
-     * <p>This method delegates to the
-     * {@link RMIClassLoaderSpi#getClassLoader(String)} method
-     * of the provider instance, passing <code>codebase</code> as the argument.
-     *
-     * <p>If there is a security manger, its <code>checkPermission</code>
-     * method will be invoked with a
-     * <code>RuntimePermission("getClassLoader")</code> permission;
-     * this could result in a <code>SecurityException</code>.
-     * The provider implementation of this method may also perform further
-     * security checks to verify that the calling context has permission to
-     * connect to all of the URIs in the codebase URI path.
-     *
-     * @param   codebase the list of URIs (space-separated) from which
-     * the returned class loader will load classes from, or <code>null</code>
-     *
-     * @return a class loader that loads classes from the given codebase URI
-     * path
-     *
-     * @throws  MalformedURLException if <code>codebase</code> is
-     * non-<code>null</code> and contains an non RFC3986 compliant URI, or
-     * if <code>codebase</code> is <code>null</code> and a provider-specific
-     * URL used to identify the class loader is invalid
-     *
-     * @throws  SecurityException if there is a security manager and the
-     * invocation of its <code>checkPermission</code> method fails, or
-     * if the caller does not have permission to connect to all of the
-     * URIs in the codebase URI path
-     * @since 3.0
-     */
-    public static ClassLoader getClassLoader(String codebase)
-        throws MalformedURLException, SecurityException
-    {
-        if (provider != null) return provider.getClassLoader(codebase);
-        return RMIClassLoader.getClassLoader(codebase);
-    }
-
-    /**
-     * Returns the annotation string (representing a location for
-     * the class definition as a single or space delimited list of
-     * RFC3986 compliant URI) that JERI will use to annotate the class
-     * descriptor when marshalling objects of the given class.
-     *
-     * <p>This method delegates to the
-     * {@link RMIClassLoaderSpi#getClassAnnotation(Class)} method
-     * of the provider instance, passing <code>cl</code> as the argument.
-     *
-     * @param   cl the class to obtain the annotation for
-     *
-     * @return  a string to be used to annotate the given class when
-     * it gets marshalled, or <code>null</code>
-     *
-     * @throws  NullPointerException if <code>cl</code> is <code>null</code>
-     * @since 3.0
-     */
-    public static String getClassAnnotation(Class<?> cl) {
-        if (provider != null) return provider.getClassAnnotation(cl);
-        return RMIClassLoader.getClassAnnotation(cl);
-    }
-
-    /**
-     * Loads a class using {@link
-     * RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}, 
-     * optionally verifying that the RFC3986 compliant
-     * codebase URIs provide content integrity.
-     *
-     * <p>If <code>verifyCodebaseIntegrity</code> is <code>true</code>
-     * and <code>codebase</code> is not <code>null</code>, then this
-     * method invokes {@link Security#verifyCodebaseIntegrity
-     * Security.verifyCodebaseIntegrity} with <code>codebase</code> as
-     * the first argument and <code>verifierLoader</code> as the
-     * second argument (this invocation may be skipped if a previous
-     * invocation of this method or {@link #loadProxyClass
-     * loadProxyClass} has already invoked
-     * <code>Security.verifyCodebaseIntegrity</code> with the same
-     * value of <code>codebase</code> and the same effective value of
-     * <code>verifierLoader</code> as arguments without it throwing an
-     * exception).  If <code>Security.verifyCodebaseIntegrity</code>
-     * throws a <code>SecurityException</code>, then this method
-     * proceeds as if <code>codebase</code> were <code>null</code>.
-     * If <code>Security.verifyCodebaseIntegrity</code> throws any
-     * other exception, then this method throws that exception.
-     *
-     * <p>This method then invokes {@link
-     * RMIClassLoaderSpi#loadClass(String,String,ClassLoader)
-     * RMIClassLoaderSpi.loadClass} with <code>codebase</code> as the
-     * first argument (or <code>null</code> if in the previous step
-     * <code>Security.verifyCodebaseIntegrity</code> was invoked and
-     * it threw a <code>SecurityException</code>), <code>name</code>
-     * as the second argument, and <code>defaultLoader</code> as the
-     * third argument.  If <code>RMIClassLoaderSpi.loadClass</code>
-     * throws a <code>ClassNotFoundException</code>, then this method
-     * throws a <code>ClassNotFoundException</code>; if
-     * <code>RMIClassLoaderSpi.loadClass</code> throws any other
-     * exception, then this method throws that exception; otherwise,
-     * this method returns the <code>Class</code> returned by
-     * <code>RMIClassLoaderSpi.loadClass</code>.
-     *
-     * @param codebase the list of URLs (separated by spaces) to load
-     * the class from, or <code>null</code>
-     *
-     * @param name the name of the class to load
-     *
-     * @param defaultLoader the class loader value (possibly
-     * <code>null</code>) to pass as the <code>defaultLoader</code>
-     * argument to <code>RMIClassLoaderSpi.loadClass</code>
-     *
-     * @param verifyCodebaseIntegrity if <code>true</code>, verify
-     * that the RFC3986 compliant codebase URIs provide content integrity
-     *
-     * @param verifierLoader the class loader value (possibly
-     * <code>null</code>) to pass to
-     * <code>Security.verifyCodebaseIntegrity</code>, if
-     * <code>verifyCodebaseIntegrity</code> is <code>true</code>
-     *
-     * @return the <code>Class</code> object representing the loaded
-     * class
-     *
-     * @throws MalformedURLException if
-     * <code>Security.verifyCodebaseIntegrity</code> or
-     * <code>RMIClassLoaderSpi.loadClass</code> throws a
-     * <code>MalformedURLException</code>
-     *
-     * @throws ClassNotFoundException if
-     * <code>RMIClassLoaderSpi.loadClass</code> throws a
-     * <code>ClassNotFoundException</code>
-     *
-     * @throws NullPointerException if <code>name</code> is
-     * <code>null</code>
-     **/
-    public static Class<?> loadClass(String codebase,
-				  String name,
-				  ClassLoader defaultLoader,
-				  boolean verifyCodebaseIntegrity,
-				  ClassLoader verifierLoader)
-	throws MalformedURLException, ClassNotFoundException
-    {
-	SecurityException verifyException = null;
-	if (verifyCodebaseIntegrity && codebase != null) {
-	    try {
-		verifyIntegrity(codebase, verifierLoader);
-	    } catch (SecurityException e) {
-		verifyException = e;
-		codebase = null;
-	    }
-	}
-	try {
-            if (provider != null) 
-                return provider.loadClass(codebase, name, defaultLoader);
-	    return RMIClassLoader.loadClass(codebase, name, defaultLoader);
-	} catch (ClassNotFoundException e) {
-	    if (verifyException != null) {
-		// assume that the verify exception is more important
-		throw new ClassNotFoundException(e.getMessage(),
-						 verifyException);
-	    } else {
-                e.fillInStackTrace();
-		throw e;
-	    }
-	}
-    }
-
-    /**
-     * Loads a dynamic proxy class using {@link
-     * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)},
-     * optionally verifying that the RFC3986 compliant
-     * codebase URIs provide content integrity.
-     *
-     * <p>If <code>verifyCodebaseIntegrity</code> is <code>true</code>
-     * and <code>codebase</code> is not <code>null</code>, then this
-     * method invokes {@link Security#verifyCodebaseIntegrity
-     * Security.verifyCodebaseIntegrity} with <code>codebase</code> as
-     * the first argument and <code>verifierLoader</code> as the
-     * second argument (this invocation may be skipped if a previous
-     * invocation of this method or {@link #loadClass loadClass} has
-     * already invoked <code>Security.verifyCodebaseIntegrity</code>
-     * with the same value of <code>codebase</code> and the same
-     * effective value of <code>verifierLoader</code> as arguments
-     * without it throwing an exception).  If
-     * <code>Security.verifyCodebaseIntegrity</code> throws a
-     * <code>SecurityException</code>, then this method proceeds as if
-     * <code>codebase</code> were <code>null</code>.  If
-     * <code>Security.verifyCodebaseIntegrity</code> throws any other
-     * exception, then this method throws that exception.
-     *
-     * <p>This method invokes {@link
-     * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)} 
-     * with <code>codebase</code> as
-     * the first argument (or <code>null</code> if in the previous
-     * step <code>Security.verifyCodebaseIntegrity</code> was invoked
-     * and it threw a <code>SecurityException</code>),
-     * <code>interfaceNames</code> as the second argument, and
-     * <code>defaultLoader</code> as the third argument.  If
-     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws a
-     * <code>ClassNotFoundException</code>, then this method throws a
-     * <code>ClassNotFoundException</code>; if
-     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws any other
-     * exception, then this method throws that exception; otherwise,
-     * this method returns the <code>Class</code> returned by
-     * <code>RMIClassLoaderSpi.loadProxyClass</code>.
-     *
-     * @param codebase the list of URLs (separated by spaces) to load
-     * classes from, or <code>null</code>
-     *
-     * @param interfaceNames the names of the interfaces for the proxy
-     * class to implement
-     *
-     * @param defaultLoader the class loader value (possibly
-     * <code>null</code>) to pass as the <code>defaultLoader</code>
-     * argument to <code>RMIClassLoader.loadProxyClass</code>
-     *
-     * @param verifyCodebaseIntegrity if <code>true</code>, verify
-     * that the codebase URLs provide content integrity
-     *
-     * @param verifierLoader the class loader value (possibly
-     * <code>null</code>) to pass to
-     * <code>Security.verifyCodebaseIntegrity</code>, if
-     * <code>verifyCodebaseIntegrity</code> is <code>true</code>
-     *
-     * @return the <code>Class</code> object representing the loaded
-     * dynamic proxy class
-     *
-     * @throws MalformedURLException if
-     * <code>Security.verifyCodebaseIntegrity</code> or
-     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws a
-     * <code>MalformedURLException</code>
-     *
-     * @throws ClassNotFoundException if
-     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws a
-     * <code>ClassNotFoundException</code>
-     *
-     * @throws NullPointerException if <code>interfaceNames</code> is
-     * <code>null</code> or if any element of
-     * <code>interfaceNames</code> is <code>null</code>
-     **/
-    public static Class<?> loadProxyClass(String codebase,
-				       String[] interfaceNames,
-				       ClassLoader defaultLoader,
-				       boolean verifyCodebaseIntegrity,
-				       ClassLoader verifierLoader)
-	throws MalformedURLException, ClassNotFoundException
-    {
-	SecurityException verifyException = null;
-	if (verifyCodebaseIntegrity && codebase != null) {
-	    try {
-		verifyIntegrity(codebase, verifierLoader);
-	    } catch (SecurityException e) {
-		verifyException = e;
-		codebase = null;
-	    }
-	}
-	try {
-            if (provider != null) return 
-                provider.loadProxyClass(codebase, interfaceNames, defaultLoader);
-	    return RMIClassLoader.loadProxyClass(codebase, interfaceNames,
-						 defaultLoader);
-	} catch (ClassNotFoundException e) {
-	    if (verifyException != null) {
-		// assume that the verify exception is more important
-		throw new ClassNotFoundException(e.getMessage(),
-						 verifyException);
-	    } else {
-                e.fillInStackTrace();
-		throw e;
-	    }
-	}
-    }
-
-    /**
-     * Wraps Security.verifyCodebaseIntegrity with caching for
-     * performance.  (Perhaps such caching should be done by
-     * Security.verifyCodebaseIntegrity instead.)
-     **/
-    private static void verifyIntegrity(String codebase,
-					ClassLoader verifierLoader)
-	throws MalformedURLException
-    {
-	/*
-	 * Check if we've already verified the same codebase in this
-	 * thread using the same verifierLoader value.
-	 */
-	Map verifierLoaderCache = (Map) perThreadCache.get();
-	// defend against varying context class loader value of thread
-	ClassLoader verifierLoaderKey =
-	    (verifierLoader != null ? verifierLoader :
-	     (ClassLoader) AccessController.doPrivileged(
-		new PrivilegedAction() {
-		    public Object run() {
-			return Thread.currentThread().getContextClassLoader();
-		    }
-		}));
-	Map verifiedCodebases =
-	    (Map) verifierLoaderCache.get(verifierLoaderKey);
-	if (verifiedCodebases != null &&
-	    verifiedCodebases.containsKey(codebase))
-	{
-	    return;
-	}
-
-	Security.verifyCodebaseIntegrity(codebase, verifierLoader);
-
-	/*
-	 * Remember that we've verified this codebase in this thread
-	 * with the given verifierLoader value.
-	 */
-	if (verifiedCodebases == null) {
-	    verifiedCodebases = new WeakHashMap();
-	    verifierLoaderCache.put(verifierLoaderKey, verifiedCodebases);
-	}
-	verifiedCodebases.put(codebase, new SoftReference(codebase));
-	return;
-    }
-    
-    /**
-     * Returns the {@code Class} object associated with the class or
-     * interface with the given string name, using the given class loader.
-     * 
-     * This method calls {@link Class#forName(String,boolean,ClassLoader)}, 
-     * from a Thread dedicated for each
-     * ClassLoader, avoiding contention for ClassLoader locks by thread
-     * confinement.  This provides a significant scalability benefit for
-     * JERI, without needing to resort to parallel ClassLoader locks, which 
-     * isn't part of the Java specification.
-     * 
-     * If loader is null, thread confinement is not used.
-     * 
-     * @param name       fully qualified name of the desired class
-     * @param initialize whether the class must be initialized
-     * @param loader     class loader from which the class must be loaded
-     * @return           class object representing the desired class
-     *
-     * @exception LinkageError if the linkage fails
-     * @exception ExceptionInInitializerError if the initialization provoked
-     *            by this method fails
-     * @exception ClassNotFoundException if the class cannot be located by
-     *            the specified class loader
-     * @see Class
-     * @since 3.0
-     */
-    public static Class<?> forName(String name, boolean initialize,
-                                   ClassLoader loader)
-        throws ClassNotFoundException
-    {
-        if (loader == null) return Class.forName(name, initialize, loader);
-        // Don't thread confine profiler ClassLoaders.
-        if (loader.toString().startsWith("javax.management.remote.rmi.RMIConnectionImpl") ) 
-            return Class.forName(name, initialize, loader);
-            
-        ExecutorService exec = loaderMap.get(loader);
-        if (exec == null){
-            exec = new ThreadPoolExecutor(
-                    1,
-                    1,
-                    0,
-                    TimeUnit.SECONDS,
-                    new LinkedBlockingQueue(),
-                    new NamedThreadFactory(loader.toString(),true),
-                    new ThreadPoolExecutor.CallerRunsPolicy()
-            );
-            ExecutorService existed = loaderMap.putIfAbsent(loader, exec);
-            if (existed != null){
-                exec = existed;
-            }
-        }
-        FutureTask<Class> future = new FutureTask(new GetClassTask(name, initialize, loader));
-        exec.submit(future);
-        try {
-            return future.get();
-        } catch (InterruptedException e){
-            e.fillInStackTrace();
-            throw new ClassNotFoundException("Interrupted, Unable to find Class: " + name, e);
-        } catch (ExecutionException e){
-            Throwable t = e.getCause();
-            if (t instanceof LinkageError) throw (LinkageError) t;
-            if (t instanceof ExceptionInInitializerError) 
-                throw (ExceptionInInitializerError) t;
-            if (t instanceof SecurityException) throw (SecurityException) t;
-            if (t instanceof ClassNotFoundException ) 
-                throw (ClassNotFoundException) t;
-            if (t instanceof NullPointerException) throw (NullPointerException) t;
-            throw new ClassNotFoundException("Unable to find Class:" + name, t);
-        }
-    }
-    
-    private static class GetClassTask implements Callable<Class> {
-        private final String name;
-        private final boolean initialize;
-        private final ClassLoader loader;
-        
-        private GetClassTask(String name, boolean initialize, ClassLoader loader){
-            this.name = name;
-            this.initialize = initialize;
-            this.loader = loader;
-        }
-
-        @Override
-        public Class call() throws ClassNotFoundException {
-            return Class.forName(name, initialize, loader);
-        }
-        
-    }
-
-    private ClassLoading() { throw new AssertionError(); }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.jini.loader;
+
+import au.net.zeus.collection.RC;
+import au.net.zeus.collection.Ref;
+import au.net.zeus.collection.Referrer;
+import java.lang.ref.SoftReference;
+import java.net.MalformedURLException;
+import java.rmi.server.RMIClassLoader;
+import java.rmi.server.RMIClassLoaderSpi;
+import java.security.AccessController;
+import java.security.Guard;
+import java.security.PrivilegedAction;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.WeakHashMap;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.jini.security.Security;
+import org.apache.river.impl.thread.NamedThreadFactory;
+
+/**
+ * Provides static methods for loading classes using {@link
+ * RMIClassLoaderSpi} with optional verification that the codebase URIs
+ * used to load classes provide content integrity (see {@link
+ * Security#verifyCodebaseIntegrity
+ * Security.verifyCodebaseIntegrity}).
+ * <p>
+ * Traditionally a class extending {@link RMIClassLoaderSpi} is determined by setting
+ * the system property "java.rmi.server.RMIClassLoaderSpi", or alternatively,
+ * {@link RMIClassLoaderSpi} may also be defined by {@link RMIClassLoader}
+ * using a provider visible to the {@link ClassLoader} returned by 
+ * {@link ClassLoader#getSystemClassLoader} with {@link ServiceLoader}.
+ * </p><p>
+ * As explained in River-336 this isn't always practical for IDE's or other 
+ * frameworks.  To solve River-336, ClassLoading now uses {@link ServiceLoader}
+ * to determine a {@link RMIClassLoaderSpi} provider, however unlike 
+ * {@link RMIClassLoader}, by default it uses ClassLoading's {@link ClassLoader#getResources} 
+ * instance to find providers.
+ * </p><p>
+ * To define a new RMIClassLoaderSpi for River to utilize, create a file in
+ * your providers jar file called:
+ * </p><p>
+ * META-INF/services/java.rmi.server.RMIClassLoaderSpi
+ * </p><p>
+ * This file should contain a single line with the fully qualified name of
+ * your RMIClassLoaderSpi implementation.
+ * </p><p>
+ * ClassLoading will iterate through all RMIClassLoaderSpi implementations found
+ * until it finds one defined by the system property:
+ * </p><p>
+ * System.getProperty("net.jini.loader.ClassLoading.provider");
+ * </p><p>
+ * If this System property is not defined, ClassLoading will load 
+ * <code>net.jini.loader.pref.PreferredClassProvider</code>, alternatively
+ * <code>java.rmi.server.RMIClassLoader</code> delegates all calls to {@link
+ * RMIClassLoader}.
+ * </p><p>
+ * If a provider is not found, it will not be updated.
+ * </p><p>
+ * <h1>History</h1>
+ * <p>Gregg Wonderly originally reported River-336 and provided a patch
+ * containing a new CodebaseAccessClassLoader to replace {@link RMIClassLoader}, 
+ * later Sim Isjkes created RiverClassLoader that utilized ServiceLoader.
+ * Both implementations contained methods identical to {@link RMIClassLoaderSpi},
+ * however new implementations were required to extend new provider 
+ * implementations, creating a compatibility issue with existing implementations
+ * extending {@link RMIClassLoaderSpi}.  For backward compatibility with existing
+ * implementations, {@link RMIClassLoaderSpi} has been retained as the provider,
+ * avoiding the need to recompile client code.  The abilities of both
+ * implementations, to use ServiceLoader, or to define a provider using a method
+ * call have been retained, with the restriction that implementations are to be
+ * obtained via ServiceLoader.
+ * </p><p>
+ * Instead, all that is required for utilization of existing service provider
+ * {@link RMIClassLoaderSpi} implementations is to set the system property
+ * "net.jini.loader.ClassLoading.provider".
+ * </p>
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ **/
+public final class ClassLoading {
+    private final static Logger logger = Logger.getLogger(ClassLoading.class.getName());
+    private static volatile RMIClassLoaderSpi provider;
+    private static final Object lock = new Object();
+    private static final Guard permission = new RuntimePermission("setFactory");
+    
+    static {
+        provider(null, ClassLoading.class.getClassLoader());
+    }
+    
+    /**
+     * The current RMIClassLoaderSpi provider in use by ClassLoading.
+     * 
+     * @return currently installed Provider, may be null.
+     * @throws SecurityException if caller doesn't have RuntimePermission "getFactory"
+     */
+    public static RMIClassLoaderSpi getProvider(){
+        permission.checkGuard(null);
+        return provider;
+    }
+    
+    private static boolean provider(
+            final String providerName, 
+            final ClassLoader providerLoader)
+    {
+        RMIClassLoaderSpi newProvider = AccessController.doPrivileged(
+        new PrivilegedAction<RMIClassLoaderSpi>(){
+            @Override
+            public RMIClassLoaderSpi run() {
+                String name = providerName;
+                if (name == null){
+                    name = System.getProperty(
+                            "net.jini.loader.ClassLoading.provider");
+                    if (name == null) {
+                        name = "net.jini.loader.pref.PreferredClassProvider";
+                    } else if ("java.rmi.server.RMIClassLoader".equals(name)){
+                        return null;
+                    }
+                }
+                ServiceLoader<RMIClassLoaderSpi> loader 
+                   = ServiceLoader.load(RMIClassLoaderSpi.class, providerLoader);
+                Iterator<RMIClassLoaderSpi> iter = loader.iterator();
+                RMIClassLoaderSpi spi;
+                while ( iter.hasNext() ) {
+                    try {
+                        spi = iter.next();
+                        if (spi != null) {
+                            if (!name.equals(spi.getClass().getName()))
+                                continue;
+                            logger.log(Level.CONFIG, "loaded: {0}", name);
+                            return spi;
+                        }
+                    } catch (Exception e) {
+                        logger.log( 
+                                Level.CONFIG, 
+                                "error loading RMIClassLoaderSpi: {0}",
+                                new Object[]{e}
+                        );
+                    }
+                }
+                logger.log(Level.CONFIG, "uable to find {0}" , name);
+                return null;
+            }
+        });
+        if (newProvider != null) {
+            provider = newProvider;
+            return true;
+        } else if (providerName == null) {
+            provider = null;
+            logger.log(Level.CONFIG, "loaded: java.rmi.server.RMIClassLoader");
+        }
+        return false;
+    }
+    
+    /**
+     * Installs a new RMIClassLoaderSpi provider with the ClassLoader 
+     * provided.
+     * 
+     * @param providerName fully defined class name of the provider, if null,
+     * a new provider instance will be determined by system properties.
+     * @param providerLoader The class loader to be used to load 
+     * provider-configuration files and provider classes, or null if the 
+     * system class loader (or, failing that, the bootstrap class loader) 
+     * is to be used.
+     * @return true if successful.
+     * @throws SecurityException if caller doesn't have RuntimePermission "getFactory"
+     */
+    public static boolean installNewProvider(
+            String providerName, 
+            ClassLoader providerLoader)
+    {
+        permission.checkGuard(null);
+        synchronized (lock){
+            return provider(providerName, providerLoader);
+        }
+    }
+    
+    /**
+     * loaderMap contains a list of single threaded ExecutorService's for
+     * each ClassLoader, used for loading classes and proxies to avoid 
+     * ClassLoader lock contention. An Entry is removed if the ClassLoader
+     * becomes weakly reachable, or the ExecutorService hasn't been used
+     * recently.
+     */
+    private static final ConcurrentMap<ClassLoader,ExecutorService> loaderMap 
+            = RC.concurrentMap(
+                new ConcurrentHashMap<Referrer<ClassLoader>,Referrer<ExecutorService>>(),
+                Ref.WEAK_IDENTITY,
+                Ref.TIME,
+                10000L,
+                10000L
+            );
+
+    /**
+     * per-thread cache (weakly) mapping verifierLoader values to
+     * (soft) sets of codebase values that have been verified (to
+     * provide content integrity) with the verifierLoader value
+     **/
+    private static final ThreadLocal perThreadCache = new ThreadLocal() {
+	protected Object initialValue() { return new WeakHashMap(); }
+    };
+    
+        /**
+     * Returns a class loader that loads classes from the given codebase
+     * RFC3986 compliant URI path.
+     *
+     * <p>This method delegates to the
+     * {@link RMIClassLoaderSpi#getClassLoader(String)} method
+     * of the provider instance, passing <code>codebase</code> as the argument.
+     *
+     * <p>If there is a security manger, its <code>checkPermission</code>
+     * method will be invoked with a
+     * <code>RuntimePermission("getClassLoader")</code> permission;
+     * this could result in a <code>SecurityException</code>.
+     * The provider implementation of this method may also perform further
+     * security checks to verify that the calling context has permission to
+     * connect to all of the URIs in the codebase URI path.
+     *
+     * @param   codebase the list of URIs (space-separated) from which
+     * the returned class loader will load classes from, or <code>null</code>
+     *
+     * @return a class loader that loads classes from the given codebase URI
+     * path
+     *
+     * @throws  MalformedURLException if <code>codebase</code> is
+     * non-<code>null</code> and contains an non RFC3986 compliant URI, or
+     * if <code>codebase</code> is <code>null</code> and a provider-specific
+     * URL used to identify the class loader is invalid
+     *
+     * @throws  SecurityException if there is a security manager and the
+     * invocation of its <code>checkPermission</code> method fails, or
+     * if the caller does not have permission to connect to all of the
+     * URIs in the codebase URI path
+     * @since 3.0
+     */
+    public static ClassLoader getClassLoader(String codebase)
+        throws MalformedURLException, SecurityException
+    {
+        if (provider != null) return provider.getClassLoader(codebase);
+        return RMIClassLoader.getClassLoader(codebase);
+    }
+
+    /**
+     * Returns the annotation string (representing a location for
+     * the class definition as a single or space delimited list of
+     * RFC3986 compliant URI) that JERI will use to annotate the class
+     * descriptor when marshalling objects of the given class.
+     *
+     * <p>This method delegates to the
+     * {@link RMIClassLoaderSpi#getClassAnnotation(Class)} method
+     * of the provider instance, passing <code>cl</code> as the argument.
+     *
+     * @param   cl the class to obtain the annotation for
+     *
+     * @return  a string to be used to annotate the given class when
+     * it gets marshalled, or <code>null</code>
+     *
+     * @throws  NullPointerException if <code>cl</code> is <code>null</code>
+     * @since 3.0
+     */
+    public static String getClassAnnotation(Class<?> cl) {
+        if (provider != null) return provider.getClassAnnotation(cl);
+        return RMIClassLoader.getClassAnnotation(cl);
+    }
+
+    /**
+     * Loads a class using {@link
+     * RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}, 
+     * optionally verifying that the RFC3986 compliant
+     * codebase URIs provide content integrity.
+     *
+     * <p>If <code>verifyCodebaseIntegrity</code> is <code>true</code>
+     * and <code>codebase</code> is not <code>null</code>, then this
+     * method invokes {@link Security#verifyCodebaseIntegrity
+     * Security.verifyCodebaseIntegrity} with <code>codebase</code> as
+     * the first argument and <code>verifierLoader</code> as the
+     * second argument (this invocation may be skipped if a previous
+     * invocation of this method or {@link #loadProxyClass
+     * loadProxyClass} has already invoked
+     * <code>Security.verifyCodebaseIntegrity</code> with the same
+     * value of <code>codebase</code> and the same effective value of
+     * <code>verifierLoader</code> as arguments without it throwing an
+     * exception).  If <code>Security.verifyCodebaseIntegrity</code>
+     * throws a <code>SecurityException</code>, then this method
+     * proceeds as if <code>codebase</code> were <code>null</code>.
+     * If <code>Security.verifyCodebaseIntegrity</code> throws any
+     * other exception, then this method throws that exception.
+     *
+     * <p>This method then invokes {@link
+     * RMIClassLoaderSpi#loadClass(String,String,ClassLoader)
+     * RMIClassLoaderSpi.loadClass} with <code>codebase</code> as the
+     * first argument (or <code>null</code> if in the previous step
+     * <code>Security.verifyCodebaseIntegrity</code> was invoked and
+     * it threw a <code>SecurityException</code>), <code>name</code>
+     * as the second argument, and <code>defaultLoader</code> as the
+     * third argument.  If <code>RMIClassLoaderSpi.loadClass</code>
+     * throws a <code>ClassNotFoundException</code>, then this method
+     * throws a <code>ClassNotFoundException</code>; if
+     * <code>RMIClassLoaderSpi.loadClass</code> throws any other
+     * exception, then this method throws that exception; otherwise,
+     * this method returns the <code>Class</code> returned by
+     * <code>RMIClassLoaderSpi.loadClass</code>.
+     *
+     * @param codebase the list of URLs (separated by spaces) to load
+     * the class from, or <code>null</code>
+     *
+     * @param name the name of the class to load
+     *
+     * @param defaultLoader the class loader value (possibly
+     * <code>null</code>) to pass as the <code>defaultLoader</code>
+     * argument to <code>RMIClassLoaderSpi.loadClass</code>
+     *
+     * @param verifyCodebaseIntegrity if <code>true</code>, verify
+     * that the RFC3986 compliant codebase URIs provide content integrity
+     *
+     * @param verifierLoader the class loader value (possibly
+     * <code>null</code>) to pass to
+     * <code>Security.verifyCodebaseIntegrity</code>, if
+     * <code>verifyCodebaseIntegrity</code> is <code>true</code>
+     *
+     * @return the <code>Class</code> object representing the loaded
+     * class
+     *
+     * @throws MalformedURLException if
+     * <code>Security.verifyCodebaseIntegrity</code> or
+     * <code>RMIClassLoaderSpi.loadClass</code> throws a
+     * <code>MalformedURLException</code>
+     *
+     * @throws ClassNotFoundException if
+     * <code>RMIClassLoaderSpi.loadClass</code> throws a
+     * <code>ClassNotFoundException</code>
+     *
+     * @throws NullPointerException if <code>name</code> is
+     * <code>null</code>
+     **/
+    public static Class<?> loadClass(String codebase,
+				  String name,
+				  ClassLoader defaultLoader,
+				  boolean verifyCodebaseIntegrity,
+				  ClassLoader verifierLoader)
+	throws MalformedURLException, ClassNotFoundException
+    {
+	SecurityException verifyException = null;
+	if (verifyCodebaseIntegrity && codebase != null) {
+	    try {
+		verifyIntegrity(codebase, verifierLoader);
+	    } catch (SecurityException e) {
+		verifyException = e;
+		codebase = null;
+	    }
+	}
+	try {
+            if (provider != null) 
+                return provider.loadClass(codebase, name, defaultLoader);
+	    return RMIClassLoader.loadClass(codebase, name, defaultLoader);
+	} catch (ClassNotFoundException e) {
+	    if (verifyException != null) {
+		// assume that the verify exception is more important
+		throw new ClassNotFoundException(e.getMessage(),
+						 verifyException);
+	    } else {
+                e.fillInStackTrace();
+		throw e;
+	    }
+	}
+    }
+
+    /**
+     * Loads a dynamic proxy class using {@link
+     * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)},
+     * optionally verifying that the RFC3986 compliant
+     * codebase URIs provide content integrity.
+     *
+     * <p>If <code>verifyCodebaseIntegrity</code> is <code>true</code>
+     * and <code>codebase</code> is not <code>null</code>, then this
+     * method invokes {@link Security#verifyCodebaseIntegrity
+     * Security.verifyCodebaseIntegrity} with <code>codebase</code> as
+     * the first argument and <code>verifierLoader</code> as the
+     * second argument (this invocation may be skipped if a previous
+     * invocation of this method or {@link #loadClass loadClass} has
+     * already invoked <code>Security.verifyCodebaseIntegrity</code>
+     * with the same value of <code>codebase</code> and the same
+     * effective value of <code>verifierLoader</code> as arguments
+     * without it throwing an exception).  If
+     * <code>Security.verifyCodebaseIntegrity</code> throws a
+     * <code>SecurityException</code>, then this method proceeds as if
+     * <code>codebase</code> were <code>null</code>.  If
+     * <code>Security.verifyCodebaseIntegrity</code> throws any other
+     * exception, then this method throws that exception.
+     *
+     * <p>This method invokes {@link
+     * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)} 
+     * with <code>codebase</code> as
+     * the first argument (or <code>null</code> if in the previous
+     * step <code>Security.verifyCodebaseIntegrity</code> was invoked
+     * and it threw a <code>SecurityException</code>),
+     * <code>interfaceNames</code> as the second argument, and
+     * <code>defaultLoader</code> as the third argument.  If
+     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws a
+     * <code>ClassNotFoundException</code>, then this method throws a
+     * <code>ClassNotFoundException</code>; if
+     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws any other
+     * exception, then this method throws that exception; otherwise,
+     * this method returns the <code>Class</code> returned by
+     * <code>RMIClassLoaderSpi.loadProxyClass</code>.
+     *
+     * @param codebase the list of URLs (separated by spaces) to load
+     * classes from, or <code>null</code>
+     *
+     * @param interfaceNames the names of the interfaces for the proxy
+     * class to implement
+     *
+     * @param defaultLoader the class loader value (possibly
+     * <code>null</code>) to pass as the <code>defaultLoader</code>
+     * argument to <code>RMIClassLoader.loadProxyClass</code>
+     *
+     * @param verifyCodebaseIntegrity if <code>true</code>, verify
+     * that the codebase URLs provide content integrity
+     *
+     * @param verifierLoader the class loader value (possibly
+     * <code>null</code>) to pass to
+     * <code>Security.verifyCodebaseIntegrity</code>, if
+     * <code>verifyCodebaseIntegrity</code> is <code>true</code>
+     *
+     * @return the <code>Class</code> object representing the loaded
+     * dynamic proxy class
+     *
+     * @throws MalformedURLException if
+     * <code>Security.verifyCodebaseIntegrity</code> or
+     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws a
+     * <code>MalformedURLException</code>
+     *
+     * @throws ClassNotFoundException if
+     * <code>RMIClassLoaderSpi.loadProxyClass</code> throws a
+     * <code>ClassNotFoundException</code>
+     *
+     * @throws NullPointerException if <code>interfaceNames</code> is
+     * <code>null</code> or if any element of
+     * <code>interfaceNames</code> is <code>null</code>
+     **/
+    public static Class<?> loadProxyClass(String codebase,
+				       String[] interfaceNames,
+				       ClassLoader defaultLoader,
+				       boolean verifyCodebaseIntegrity,
+				       ClassLoader verifierLoader)
+	throws MalformedURLException, ClassNotFoundException
+    {
+	SecurityException verifyException = null;
+	if (verifyCodebaseIntegrity && codebase != null) {
+	    try {
+		verifyIntegrity(codebase, verifierLoader);
+	    } catch (SecurityException e) {
+		verifyException = e;
+		codebase = null;
+	    }
+	}
+	try {
+            if (provider != null) return 
+                provider.loadProxyClass(codebase, interfaceNames, defaultLoader);
+	    return RMIClassLoader.loadProxyClass(codebase, interfaceNames,
+						 defaultLoader);
+	} catch (ClassNotFoundException e) {
+	    if (verifyException != null) {
+		// assume that the verify exception is more important
+		throw new ClassNotFoundException(e.getMessage(),
+						 verifyException);
+	    } else {
+                e.fillInStackTrace();
+		throw e;
+	    }
+	}
+    }
+
+    /**
+     * Wraps Security.verifyCodebaseIntegrity with caching for
+     * performance.  (Perhaps such caching should be done by
+     * Security.verifyCodebaseIntegrity instead.)
+     **/
+    private static void verifyIntegrity(String codebase,
+					ClassLoader verifierLoader)
+	throws MalformedURLException
+    {
+	/*
+	 * Check if we've already verified the same codebase in this
+	 * thread using the same verifierLoader value.
+	 */
+	Map verifierLoaderCache = (Map) perThreadCache.get();
+	// defend against varying context class loader value of thread
+	ClassLoader verifierLoaderKey =
+	    (verifierLoader != null ? verifierLoader :
+	     (ClassLoader) AccessController.doPrivileged(
+		new PrivilegedAction() {
+		    public Object run() {
+			return Thread.currentThread().getContextClassLoader();
+		    }
+		}));
+	Map verifiedCodebases =
+	    (Map) verifierLoaderCache.get(verifierLoaderKey);
+	if (verifiedCodebases != null &&
+	    verifiedCodebases.containsKey(codebase))
+	{
+	    return;
+	}
+
+	Security.verifyCodebaseIntegrity(codebase, verifierLoader);
+
+	/*
+	 * Remember that we've verified this codebase in this thread
+	 * with the given verifierLoader value.
+	 */
+	if (verifiedCodebases == null) {
+	    verifiedCodebases = new WeakHashMap();
+	    verifierLoaderCache.put(verifierLoaderKey, verifiedCodebases);
+	}
+	verifiedCodebases.put(codebase, new SoftReference(codebase));
+	return;
+    }
+    
+    /**
+     * Returns the {@code Class} object associated with the class or
+     * interface with the given string name, using the given class loader.
+     * 
+     * This method calls {@link Class#forName(String,boolean,ClassLoader)}, 
+     * from a Thread dedicated for each
+     * ClassLoader, avoiding contention for ClassLoader locks by thread
+     * confinement.  This provides a significant scalability benefit for
+     * JERI, without needing to resort to parallel ClassLoader locks, which 
+     * isn't part of the Java specification.
+     * 
+     * If loader is null, thread confinement is not used.
+     * 
+     * @param name       fully qualified name of the desired class
+     * @param initialize whether the class must be initialized
+     * @param loader     class loader from which the class must be loaded
+     * @return           class object representing the desired class
+     *
+     * @exception LinkageError if the linkage fails
+     * @exception ExceptionInInitializerError if the initialization provoked
+     *            by this method fails
+     * @exception ClassNotFoundException if the class cannot be located by
+     *            the specified class loader
+     * @see Class
+     * @since 3.0
+     */
+    public static Class<?> forName(String name, boolean initialize,
+                                   ClassLoader loader)
+        throws ClassNotFoundException
+    {
+        if (loader == null) return Class.forName(name, initialize, loader);
+        // Don't thread confine profiler ClassLoaders.
+        if (loader.toString().startsWith("javax.management.remote.rmi.RMIConnectionImpl") ) 
+            return Class.forName(name, initialize, loader);
+            
+        ExecutorService exec = loaderMap.get(loader);
+        if (exec == null){
+            exec = new ThreadPoolExecutor(
+                    1,
+                    1,
+                    0,
+                    TimeUnit.SECONDS,
+                    new LinkedBlockingQueue(),
+                    new NamedThreadFactory(loader.toString(),false),
+                    new ThreadPoolExecutor.CallerRunsPolicy()
+            );
+            ExecutorService existed = loaderMap.putIfAbsent(loader, exec);
+            if (existed != null){
+                exec = existed;
+            }
+        }
+        FutureTask<Class> future = new FutureTask(new GetClassTask(name, initialize, loader));
+        exec.submit(future);
+        try {
+            return future.get();
+        } catch (InterruptedException e){
+            e.fillInStackTrace();
+            throw new ClassNotFoundException("Interrupted, Unable to find Class: " + name, e);
+        } catch (ExecutionException e){
+            Throwable t = e.getCause();
+            if (t instanceof LinkageError) throw (LinkageError) t;
+            if (t instanceof ExceptionInInitializerError) 
+                throw (ExceptionInInitializerError) t;
+            if (t instanceof SecurityException) throw (SecurityException) t;
+            if (t instanceof ClassNotFoundException ) 
+                throw (ClassNotFoundException) t;
+            if (t instanceof NullPointerException) throw (NullPointerException) t;
+            throw new ClassNotFoundException("Unable to find Class:" + name, t);
+        }
+    }
+    
+    private static class GetClassTask implements Callable<Class> {
+        private final String name;
+        private final boolean initialize;
+        private final ClassLoader loader;
+        
+        private GetClassTask(String name, boolean initialize, ClassLoader loader){
+            this.name = name;
+            this.initialize = initialize;
+            this.loader = loader;
+        }
+
+        @Override
+        public Class call() throws ClassNotFoundException {
+            return Class.forName(name, initialize, loader);
+        }
+        
+    }
+
+    private ClassLoading() { throw new AssertionError(); }
+}