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 <rmannibu...@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; }