You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by rm...@apache.org on 2020/12/26 17:37:25 UTC

[openwebbeans] branch master updated: [OWB-1361] startup time improvements: enable to skip our noclassdeffound checks - in well known cases, enable to skip some cdi validations - once deployment is validated it helps, skip anonymous and private classes earlier in the process, enable to skip PAT event when there is no observer for it (todo: same for PIP)

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

rmannibucau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwebbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 42524ee  [OWB-1361] startup time improvements: enable to skip our noclassdeffound checks - in well known cases, enable to skip some cdi validations - once deployment is validated it helps, skip anonymous and private classes earlier in the process, enable to skip PAT event when there is no observer for it (todo: same for PIP)
42524ee is described below

commit 42524ee28e0fc2ed63ed9edb99c31edd9aca2674
Author: Romain Manni-Bucau <rm...@gmail.com>
AuthorDate: Sat Dec 26 18:37:19 2020 +0100

    [OWB-1361] startup time improvements: enable to skip our noclassdeffound checks - in well known cases, enable to skip some cdi validations - once deployment is validated it helps, skip anonymous and private classes earlier in the process, enable to skip PAT event when there is no observer for it (todo: same for PIP)
---
 .../org/apache/webbeans/config/BeansDeployer.java  |  35 ++-
 .../webbeans/config/OpenWebBeansConfiguration.java |   6 +
 .../corespi/scanner/AbstractMetaDataDiscovery.java |  14 +-
 .../apache/webbeans/event/NotificationManager.java | 309 +++++++++++----------
 .../webbeans/portable/AnnotatedElementFactory.java |   2 +-
 .../java/org/apache/webbeans/util/ClassUtil.java   |  10 +-
 6 files changed, 215 insertions(+), 161 deletions(-)

diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java b/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java
index a7b2337..5eaf2c3 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java
@@ -111,6 +111,7 @@ import javax.enterprise.inject.spi.Producer;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.net.URL;
@@ -164,6 +165,8 @@ public class BeansDeployer
     private final Map<String, Boolean> packageVetoCache = new HashMap<>();
 
     protected boolean skipVetoedOnPackages;
+    protected boolean skipNoClassDefFoundTriggers;
+    protected boolean skipValidations;
 
     /**
      * This BdaInfo is used for all manually added annotated types or in case
@@ -188,6 +191,9 @@ public class BeansDeployer
         discoverEjb = Boolean.parseBoolean(usage);
         skipVetoedOnPackages = Boolean.parseBoolean(this.webBeansContext.getOpenWebBeansConfiguration().getProperty(
                 "org.apache.webbeans.spi.deployer.skipVetoedOnPackages"));
+        skipValidations = Boolean.parseBoolean(this.webBeansContext.getOpenWebBeansConfiguration().getProperty(
+                "org.apache.webbeans.spi.deployer.skipValidations"));
+        skipNoClassDefFoundTriggers = this.webBeansContext.getOpenWebBeansConfiguration().isSkipNoClassDefFoundErrorTriggers();
 
         defaultBeanArchiveInformation = new DefaultBeanArchiveInformation("default");
         defaultBeanArchiveInformation.setBeanDiscoveryMode(BeanDiscoveryMode.ALL);
@@ -313,15 +319,18 @@ public class BeansDeployer
                 // drop no more needed memory data
                 webBeansContext.getNotificationManager().afterStart();
 
-                validateAlternatives(beanAttributesPerBda);
+                if (!skipValidations)
+                {
+                    validateAlternatives(beanAttributesPerBda);
 
-                validateInjectionPoints();
-                validateDisposeParameters();
+                    validateInjectionPoints();
+                    validateDisposeParameters();
 
-                validateDecoratorDecoratedTypes();
-                validateDecoratorGenericTypes();
+                    validateDecoratorDecoratedTypes();
+                    validateDecoratorGenericTypes();
 
-                validateNames();
+                    validateNames();
+                }
 
                 if (webBeansContext.getNotificationManager().getObserverMethods().stream()
                         .anyMatch(ObserverMethod::isAsync))
@@ -1295,10 +1304,11 @@ public class BeansDeployer
         if (classIndex != null)
         {
             AnnotatedElementFactory annotatedElementFactory = webBeansContext.getAnnotatedElementFactory();
-
+            boolean hasPATObserver = webBeansContext.getNotificationManager().hasProcessAnnotatedTypeObservers();
             for (Class<?> implClass : classIndex)
             {
-                if (foundClasses.contains(implClass))
+                if (foundClasses.contains(implClass) || implClass.isAnonymousClass() ||
+                        Modifier.isPrivate(implClass.getModifiers() /* likely inner class */))
                 {
                     // skip this class
                     continue;
@@ -1338,11 +1348,14 @@ public class BeansDeployer
 
                     // trigger a NoClassDefFoundError here, otherwise it would be thrown in observer methods
                     Class<?> javaClass = annotatedType.getJavaClass();
-                    javaClass.getDeclaredMethods();
-                    javaClass.getDeclaredFields();
+                    if (!skipNoClassDefFoundTriggers)
+                    {
+                        javaClass.getDeclaredMethods();
+                        javaClass.getDeclaredFields();
+                    }
 
                     // Fires ProcessAnnotatedType
-                    if (!javaClass.isAnnotation())
+                    if (hasPATObserver && !javaClass.isAnnotation())
                     {
                         GProcessAnnotatedType processAnnotatedEvent = webBeansContext.getWebBeansUtil().fireProcessAnnotatedTypeEvent(annotatedType);
                         if (!processAnnotatedEvent.isVeto())
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java b/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java
index 0d2b480..3810268 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java
@@ -550,4 +550,10 @@ public class OpenWebBeansConfiguration
 
         return generatorJavaVersion;
     }
+
+    public boolean isSkipNoClassDefFoundErrorTriggers()
+    {
+        return Boolean.parseBoolean(getProperty(
+                "org.apache.webbeans.spi.deployer.skipNoClassDefFoundTriggers"));
+    }
 }
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java
index 210556e..d09e2b3 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java
@@ -412,6 +412,9 @@ public abstract class AbstractMetaDataDiscovery implements BdaScannerService
         if (beanClassesPerBda == null)
         {
             beanClassesPerBda = new HashMap<>();
+            ClassLoader loader = WebBeansUtil.getCurrentClassLoader();
+            boolean dontSkipNCDFT = !(webBeansContext != null &&
+                    webBeansContext.getOpenWebBeansConfiguration().isSkipNoClassDefFoundErrorTriggers());
 
             for (CdiArchive.FoundClasses foundClasses : archive.classesByUrl().values())
             {
@@ -431,12 +434,15 @@ public abstract class AbstractMetaDataDiscovery implements BdaScannerService
                             }
                         }
 
-                        Class<?> clazz = ClassUtil.getClassFromName(className);
+                        Class<?> clazz = ClassUtil.getClassFromName(className, loader, dontSkipNCDFT);
                         if (clazz != null)
                         {
-                            // try to provoke a NoClassDefFoundError exception which is thrown
-                            // if some dependencies of the class are missing
-                            clazz.getDeclaredFields();
+                            if (dontSkipNCDFT)
+                            {
+                                // try to provoke a NoClassDefFoundError exception which is thrown
+                                // if some dependencies of the class are missing
+                                clazz.getDeclaredFields();
+                            }
 
                             // we can add this class cause it has been loaded completely
                             classSet.add(clazz);
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java b/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java
index dede48e..3ad6ce0 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java
@@ -82,6 +82,7 @@ import org.apache.webbeans.exception.WebBeansConfigurationException;
 import org.apache.webbeans.exception.WebBeansDeploymentException;
 import org.apache.webbeans.exception.WebBeansException;
 import org.apache.webbeans.logger.WebBeansLoggerFacade;
+import org.apache.webbeans.portable.events.ProcessAnnotatedTypeImpl;
 import org.apache.webbeans.portable.events.generics.GProcessObserverMethod;
 import org.apache.webbeans.portable.events.generics.GenericBeanEvent;
 import org.apache.webbeans.portable.events.generics.GenericProducerObserverEvent;
@@ -95,6 +96,7 @@ import org.apache.webbeans.util.GenericsUtil;
 import org.apache.webbeans.util.WebBeansUtil;
 
 import static java.util.Collections.emptyList;
+import static java.util.concurrent.CompletableFuture.completedFuture;
 import static java.util.stream.Collectors.toMap;
 
 public final class NotificationManager
@@ -229,196 +231,211 @@ public final class NotificationManager
         set.add(observer);
     }
 
+    public boolean hasProcessAnnotatedTypeObservers()
+    {
+        cacheIfNeeded(new ProcessAnnotatedTypeImpl<>(null, null));
+        return !processAnnotatedTypeObservers.isEmpty();
+    }
 
     public <T> Collection<ObserverMethod<? super T>> resolveObservers(T event, EventMetadataImpl metadata, boolean isLifecycleEvent)
     {
         if (isLifecycleEvent) // goal here is to skip any resolution if not needed
         {
-            if (event instanceof ProcessAnnotatedType)
+            Collection<ObserverMethod<?>> observerMethods = cacheIfNeeded(event);
+            if (observerMethods != null) // emptyList()
             {
-                if (processAnnotatedTypeObservers == null)
-                {
-                    processAnnotatedTypeObservers = findObservers(ProcessAnnotatedType.class);
-                }
-                if (processAnnotatedTypeObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                return emptyList();
             }
-            else if (event instanceof ProcessManagedBean)
+        }
+        Type eventType = metadata.validatedType();
+        Collection<ObserverMethod<? super T>> observersMethods = filterByQualifiers(
+                filterByType(event, eventType, isLifecycleEvent), metadata.getQualifiers());
+
+        if (isLifecycleEvent && event instanceof ProcessAnnotatedType)
+        {
+            observersMethods = filterByWithAnnotations(observersMethods, ((ProcessAnnotatedType) event).getAnnotatedType());
+        }
+        else if (!isLifecycleEvent && observersMethods.isEmpty())
+        {
+            //this check for the TCK is only needed if no observer was found
+            EventUtil.checkEventBindings(webBeansContext, metadata.getQualifiers());
+            EventUtil.checkQualifierImplementations(metadata.getQualifiers());
+        }
+
+        return observersMethods;
+    }
+
+    private <T> Collection<ObserverMethod<?>> cacheIfNeeded(final T event)
+    {
+        if (event instanceof ProcessAnnotatedType)
+        {
+            if (processAnnotatedTypeObservers == null)
             {
-                if (processManagedBeanObservers == null)
-                {
-                    processManagedBeanObservers = findObservers(ProcessManagedBean.class);
-                    if (processBeanObservers == null)
-                    {
-                        processBeanObservers = findObservers(ProcessBean.class);
-                    }
-                    processBeanObservers.forEach((k, v) -> processManagedBeanObservers
-                            .computeIfAbsent(k, it -> new HashSet<>())
-                            .addAll(v));
-                }
-                if (processManagedBeanObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                processAnnotatedTypeObservers = findObservers(ProcessAnnotatedType.class);
             }
-            else if (event instanceof ProcessProducerField)
+            if (processAnnotatedTypeObservers.isEmpty())
             {
-                if (processProducerFieldObservers == null)
-                {
-                    processProducerFieldObservers = findObservers(ProcessProducerField.class);
-                    if (processBeanObservers == null)
-                    {
-                        processBeanObservers = findObservers(ProcessBean.class);
-                    }
-                        processBeanObservers.forEach((k, v) -> processProducerFieldObservers
-                                .computeIfAbsent(k, it -> new HashSet<>())
-                                .addAll(v));
-                    }
-                    if (processProducerFieldObservers.isEmpty())
-                    {
-                        return emptyList();
-                    }
+                return emptyList();
             }
-            else if (event instanceof ProcessProducerMethod)
+        }
+        else if (event instanceof ProcessManagedBean)
+        {
+            if (processManagedBeanObservers == null)
             {
-                if (processProducerMethodObservers == null)
-                {
-                    processProducerMethodObservers = findObservers(ProcessProducerMethod.class);
-                    if (processBeanObservers == null)
-                    {
-                        processBeanObservers = findObservers(ProcessBean.class);
-                    }
-                    processBeanObservers.forEach((k, v) -> processProducerMethodObservers
-                            .computeIfAbsent(k, it -> new HashSet<>())
-                            .addAll(v));
-                }
-                if (processProducerMethodObservers.isEmpty())
+                processManagedBeanObservers = findObservers(ProcessManagedBean.class);
+                if (processBeanObservers == null)
                 {
-                    return emptyList();
+                    processBeanObservers = findObservers(ProcessBean.class);
                 }
+                processBeanObservers.forEach((k, v) -> processManagedBeanObservers
+                        .computeIfAbsent(k, it -> new HashSet<>())
+                        .addAll(v));
             }
-            else if (event instanceof ProcessSyntheticBean)
+            if (processManagedBeanObservers.isEmpty())
             {
-                if (processSyntheticBeanObservers == null)
-                {
-                    processSyntheticBeanObservers = findObservers(ProcessSyntheticBean.class);
-                    if (processBeanObservers == null)
-                    {
-                        processBeanObservers = findObservers(ProcessBean.class);
-                    }
-                    processBeanObservers.forEach((k, v) -> processSyntheticBeanObservers
-                            .computeIfAbsent(k, it -> new HashSet<>())
-                            .addAll(v));
-                }
-                if (processSyntheticBeanObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                return emptyList();
             }
-            else if (event instanceof ProcessSyntheticObserverMethod)
+        }
+        else if (event instanceof ProcessProducerField)
+        {
+            if (processProducerFieldObservers == null)
             {
-                if (processSyntheticObserverMethodObservers == null)
-                {
-                    processSyntheticObserverMethodObservers = findObservers(ProcessSyntheticObserverMethod.class);
-                    if (processObserverMethodObservers == null)
-                    {
-                        processObserverMethodObservers = findObservers(ProcessObserverMethod.class);
-                    }
-                    processObserverMethodObservers.forEach((k, v) -> processSyntheticObserverMethodObservers
-                            .computeIfAbsent(k, it -> new HashSet<>())
-                            .addAll(v));
-                }
-                if (processSyntheticObserverMethodObservers.isEmpty())
+                processProducerFieldObservers = findObservers(ProcessProducerField.class);
+                if (processBeanObservers == null)
                 {
-                    return emptyList();
+                    processBeanObservers = findObservers(ProcessBean.class);
                 }
+                processBeanObservers.forEach((k, v) -> processProducerFieldObservers
+                        .computeIfAbsent(k, it -> new HashSet<>())
+                        .addAll(v));
             }
-            else if (event instanceof ProcessBean)
+            if (processProducerFieldObservers.isEmpty())
             {
+                return emptyList();
+            }
+        }
+        else if (event instanceof ProcessProducerMethod)
+        {
+            if (processProducerMethodObservers == null)
+            {
+                processProducerMethodObservers = findObservers(ProcessProducerMethod.class);
                 if (processBeanObservers == null)
                 {
                     processBeanObservers = findObservers(ProcessBean.class);
                 }
-                if (processBeanObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                processBeanObservers.forEach((k, v) -> processProducerMethodObservers
+                        .computeIfAbsent(k, it -> new HashSet<>())
+                        .addAll(v));
             }
-            else if (event instanceof ProcessBeanAttributes)
+            if (processProducerMethodObservers.isEmpty())
             {
-                if (processBeanAttributesObservers == null)
-                {
-                    processBeanAttributesObservers = findObservers(ProcessBeanAttributes.class);
-                }
-                if (processBeanAttributesObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                return emptyList();
             }
-            else if (event instanceof ProcessInjectionTarget)
+        }
+        else if (event instanceof ProcessSyntheticBean)
+        {
+            if (processSyntheticBeanObservers == null)
             {
-                if (processInjectionTargetObservers == null)
-                {
-                    processInjectionTargetObservers = findObservers(ProcessInjectionTarget.class);
-                }
-                if (processInjectionTargetObservers.isEmpty())
+                processSyntheticBeanObservers = findObservers(ProcessSyntheticBean.class);
+                if (processBeanObservers == null)
                 {
-                    return emptyList();
+                    processBeanObservers = findObservers(ProcessBean.class);
                 }
+                processBeanObservers.forEach((k, v) -> processSyntheticBeanObservers
+                        .computeIfAbsent(k, it -> new HashSet<>())
+                        .addAll(v));
             }
-            else if (event instanceof ProcessInjectionPoint)
+            if (processSyntheticBeanObservers.isEmpty())
             {
-                if (processInjectionPointObservers == null)
-                {
-                    processInjectionPointObservers = findObservers(ProcessInjectionPoint.class);
-                }
-                if (processInjectionPointObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                return emptyList();
             }
-            else if (event instanceof ProcessObserverMethod)
+        }
+        else if (event instanceof ProcessSyntheticObserverMethod)
+        {
+            if (processSyntheticObserverMethodObservers == null)
             {
+                processSyntheticObserverMethodObservers = findObservers(ProcessSyntheticObserverMethod.class);
                 if (processObserverMethodObservers == null)
                 {
                     processObserverMethodObservers = findObservers(ProcessObserverMethod.class);
                 }
-                if (processObserverMethodObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                processObserverMethodObservers.forEach((k, v) -> processSyntheticObserverMethodObservers
+                        .computeIfAbsent(k, it -> new HashSet<>())
+                        .addAll(v));
             }
-            else if (event instanceof ProcessProducer)
+            if (processSyntheticObserverMethodObservers.isEmpty())
             {
-                if (processProducerObservers == null)
-                {
-                    processProducerObservers = findObservers(ProcessProducer.class);
-                }
-                if (processProducerObservers.isEmpty())
-                {
-                    return emptyList();
-                }
+                return emptyList();
             }
-            // note: don't forget to update filterByExtensionEventType method too
         }
-        Type eventType = metadata.validatedType();
-        Collection<ObserverMethod<? super T>> observersMethods = filterByQualifiers(
-                filterByType(event, eventType, isLifecycleEvent), metadata.getQualifiers());
-
-        if (isLifecycleEvent && event instanceof ProcessAnnotatedType)
+        else if (event instanceof ProcessBean)
         {
-            observersMethods = filterByWithAnnotations(observersMethods, ((ProcessAnnotatedType) event).getAnnotatedType());
+            if (processBeanObservers == null)
+            {
+                processBeanObservers = findObservers(ProcessBean.class);
+            }
+            if (processBeanObservers.isEmpty())
+            {
+                return emptyList();
+            }
         }
-        else if (!isLifecycleEvent && observersMethods.isEmpty())
+        else if (event instanceof ProcessBeanAttributes)
         {
-            //this check for the TCK is only needed if no observer was found
-            EventUtil.checkEventBindings(webBeansContext, metadata.getQualifiers());
-            EventUtil.checkQualifierImplementations(metadata.getQualifiers());
+            if (processBeanAttributesObservers == null)
+            {
+                processBeanAttributesObservers = findObservers(ProcessBeanAttributes.class);
+            }
+            if (processBeanAttributesObservers.isEmpty())
+            {
+                return emptyList();
+            }
         }
-
-        return observersMethods;
+        else if (event instanceof ProcessInjectionTarget)
+        {
+            if (processInjectionTargetObservers == null)
+            {
+                processInjectionTargetObservers = findObservers(ProcessInjectionTarget.class);
+            }
+            if (processInjectionTargetObservers.isEmpty())
+            {
+                return emptyList();
+            }
+        }
+        else if (event instanceof ProcessInjectionPoint)
+        {
+            if (processInjectionPointObservers == null)
+            {
+                processInjectionPointObservers = findObservers(ProcessInjectionPoint.class);
+            }
+            if (processInjectionPointObservers.isEmpty())
+            {
+                return emptyList();
+            }
+        }
+        else if (event instanceof ProcessObserverMethod)
+        {
+            if (processObserverMethodObservers == null)
+            {
+                processObserverMethodObservers = findObservers(ProcessObserverMethod.class);
+            }
+            if (processObserverMethodObservers.isEmpty())
+            {
+                return emptyList();
+            }
+        }
+        else if (event instanceof ProcessProducer)
+        {
+            if (processProducerObservers == null)
+            {
+                processProducerObservers = findObservers(ProcessProducer.class);
+            }
+            if (processProducerObservers.isEmpty())
+            {
+                return emptyList();
+            }
+        }
+        // note: don't forget to update filterByExtensionEventType method too
+        return null;
     }
 
     private <T> Collection<ObserverMethod<? super T>> filterByWithAnnotations(Collection<ObserverMethod<? super T>> observersMethods, AnnotatedType annotatedType)
@@ -921,6 +938,14 @@ public final class NotificationManager
                                               List<ObserverMethod<? super Object>> observerMethods)
     {
         prepareObserverListForFire(isLifecycleEvent, async, observerMethods);
+        if (observerMethods.isEmpty())
+        {
+            if (async)
+            {
+                return completedFuture((T) event);
+            }
+            return null;
+        }
         EventContextImpl<Object> context = new EventContextImpl<>(event, metadata);
         if (async)
         {
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/portable/AnnotatedElementFactory.java b/webbeans-impl/src/main/java/org/apache/webbeans/portable/AnnotatedElementFactory.java
index afa78bc..460c932 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/portable/AnnotatedElementFactory.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/portable/AnnotatedElementFactory.java
@@ -394,6 +394,6 @@ public final class AnnotatedElementFactory
                 annotatedTypes = oldAnnotatedTypes;
             }
         }
-        return (ConcurrentMap<String, AnnotatedType<T>>)(ConcurrentMap<?, ?>)annotatedTypes;
+        return ConcurrentMap.class.cast(annotatedTypes);
     }
 }
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java b/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
index 2ecce48..67b4540 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
@@ -89,12 +89,16 @@ public final class ClassUtil
 
     public static Class<?> getClassFromName(String name)
     {
+        return getClassFromName(name, WebBeansUtil.getCurrentClassLoader(), true);
+    }
+
+    public static Class<?> getClassFromName(String name, ClassLoader providedLoader, boolean init)
+    {
         Class<?> clazz;
-        ClassLoader loader;
+        ClassLoader loader = providedLoader;
         try
         {
-            loader = WebBeansUtil.getCurrentClassLoader();
-            clazz = Class.forName(name, true , loader);
+            clazz = Class.forName(name, init , loader);
             return clazz;
 
         }