You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2022/03/23 03:43:29 UTC

[logging-log4j2] branch master updated (5e37615 -> fdd78e9)

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

mattsicker pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git.


    from 5e37615  Fix broken link in MDC manual.
     new f4c6515  Refactor PluginManager usage to utilise Injector
     new fdd78e9  Revert MethodHandle usage back to reflection

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../log4j/core/config/LoggersPluginTest.java       |   2 +-
 .../java/org/apache/logging/log4j/core/Core.java   |   6 +
 .../log4j/core/config/AbstractConfiguration.java   |  34 +++-
 .../log4j/core/config/PropertiesPlugin.java        |  22 +--
 .../logging/log4j/core/impl/DefaultCallback.java   |   3 +-
 .../logging/log4j/core/lookup/Interpolator.java    |  45 +++--
 .../logging/log4j/core/lookup/StrLookup.java       |   5 +
 .../org/apache/logging/log4j/core/util/Loader.java |  50 +----
 .../apache/logging/log4j/core/util/Watcher.java    |   8 +-
 .../logging/log4j/core/util/WatcherFactory.java    |  32 +---
 .../log4j/plugin/processor/PluginProcessor.java    |   9 -
 .../logging/log4j/plugins/di/InjectorTest.java     |   3 +-
 .../logging/log4j/plugins/di/BindingMap.java       |  14 +-
 .../logging/log4j/plugins/di/DefaultInjector.java  | 205 +++++++++++----------
 .../InjectException.java}                          |  10 +-
 .../apache/logging/log4j/plugins/di/Injector.java  |  11 +-
 .../org/apache/logging/log4j/plugins/di/Key.java   |   8 +
 ...LookupSelector.java => ReflectionAccessor.java} |   6 +-
 .../log4j/plugins/processor/PluginService.java     |   5 +-
 .../logging/log4j/plugins/util/PluginManager.java  |   8 +-
 .../logging/log4j/plugins/util/PluginRegistry.java |   3 +-
 .../logging/log4j/plugins/util/PluginType.java     |  27 +--
 22 files changed, 248 insertions(+), 268 deletions(-)
 copy log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/{PluginException.java => di/InjectException.java} (76%)
 copy log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/{LookupSelector.java => ReflectionAccessor.java} (84%)

[logging-log4j2] 01/02: Refactor PluginManager usage to utilise Injector

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit f4c65158299eba194ca24e35482d25540593b795
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Mon Mar 21 18:52:17 2022 -0500

    Refactor PluginManager usage to utilise Injector
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../java/org/apache/logging/log4j/core/Core.java   |  6 +++
 .../log4j/core/config/AbstractConfiguration.java   | 34 ++++++++++-----
 .../log4j/core/config/PropertiesPlugin.java        | 22 +++++-----
 .../logging/log4j/core/lookup/Interpolator.java    | 45 ++++++++++++-------
 .../logging/log4j/core/lookup/StrLookup.java       |  5 +++
 .../org/apache/logging/log4j/core/util/Loader.java | 50 +++-------------------
 .../apache/logging/log4j/core/util/Watcher.java    |  8 +++-
 .../logging/log4j/core/util/WatcherFactory.java    | 32 ++++----------
 .../logging/log4j/plugins/di/BindingMap.java       | 14 +++++-
 .../logging/log4j/plugins/di/DefaultInjector.java  | 16 ++++---
 .../org/apache/logging/log4j/plugins/di/Key.java   |  8 ++++
 .../logging/log4j/plugins/util/PluginManager.java  |  8 +++-
 12 files changed, 130 insertions(+), 118 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java
index 6a26c04..0886a81 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java
@@ -17,8 +17,14 @@
 
 package org.apache.logging.log4j.core;
 
+import org.apache.logging.log4j.plugins.Named;
+import org.apache.logging.log4j.plugins.di.Key;
+import org.apache.logging.log4j.plugins.util.PluginManager;
+
 public class Core {
 
     public static final String CATEGORY_NAME = "Core";
 
+    public static final Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY_NAME) Key<>() {};
+
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 383ec1e..5acf726 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.config;
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Core;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
@@ -43,11 +44,11 @@ import org.apache.logging.log4j.core.script.ScriptManager;
 import org.apache.logging.log4j.core.script.ScriptManagerFactory;
 import org.apache.logging.log4j.core.time.NanoClock;
 import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.core.util.Source;
 import org.apache.logging.log4j.core.util.WatchManager;
 import org.apache.logging.log4j.core.util.Watcher;
 import org.apache.logging.log4j.core.util.WatcherFactory;
+import org.apache.logging.log4j.plugins.Named;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.di.DI;
 import org.apache.logging.log4j.plugins.di.Injector;
@@ -56,6 +57,7 @@ import org.apache.logging.log4j.plugins.di.Keys;
 import org.apache.logging.log4j.plugins.util.PluginManager;
 import org.apache.logging.log4j.plugins.util.PluginType;
 import org.apache.logging.log4j.plugins.util.TypeUtil;
+import org.apache.logging.log4j.util.LazyValue;
 import org.apache.logging.log4j.util.NameUtil;
 import org.apache.logging.log4j.util.PropertiesUtil;
 import org.apache.logging.log4j.util.ServiceRegistry;
@@ -131,9 +133,9 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
     private ConcurrentMap<String, LoggerConfig> loggerConfigs = new ConcurrentHashMap<>();
     private List<CustomLevelConfig> customLevels = List.of();
     private final ConcurrentMap<String, String> properties = new ConcurrentHashMap<>();
-    private final StrLookup tempLookup = new Interpolator(properties);
-    private final StrSubstitutor runtimeStrSubstitutor = new RuntimeStrSubstitutor(tempLookup);
-    private final StrSubstitutor configurationStrSubstitutor = new ConfigurationStrSubstitutor(runtimeStrSubstitutor);
+    private final StrLookup tempLookup;
+    private final StrSubstitutor runtimeStrSubstitutor;
+    private final StrSubstitutor configurationStrSubstitutor;
     private LoggerConfig root = new LoggerConfig();
     private final ConcurrentMap<String, Object> componentMap = new ConcurrentHashMap<>();
     private final ConfigurationSource configurationSource;
@@ -158,7 +160,10 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
             injector.init();
         }
         componentMap.put(Configuration.CONTEXT_PROPERTIES, properties);
-        pluginManager = new PluginManager(Node.CATEGORY);
+        tempLookup = new Interpolator(new PropertiesLookup(properties), this);
+        runtimeStrSubstitutor = new RuntimeStrSubstitutor(tempLookup);
+        configurationStrSubstitutor = new ConfigurationStrSubstitutor(runtimeStrSubstitutor);
+        pluginManager = injector.getInstance(Core.PLUGIN_MANAGER_KEY);
         configurationScheduler = injector.getInstance(ConfigurationScheduler.class);
         watchManager = injector.getInstance(WatchManager.class);
         setState(State.INITIALIZING);
@@ -195,6 +200,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
 
     public void setPluginManager(final PluginManager pluginManager) {
         this.pluginManager = pluginManager;
+        injector.registerBinding(Core.PLUGIN_MANAGER_KEY, this::getPluginManager);
     }
 
     @Override
@@ -232,16 +238,17 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         configurationStrSubstitutor.setConfiguration(this);
         initializeScriptManager();
         pluginManager.collectPlugins(pluginPackages);
-        final PluginManager levelPlugins = new PluginManager(Level.CATEGORY);
+        final PluginManager levelPlugins = injector.getInstance(new @Named(Level.CATEGORY) Key<>() {});
         levelPlugins.collectPlugins(pluginPackages);
         final Map<String, PluginType<?>> plugins = levelPlugins.getPlugins();
         if (plugins != null) {
             for (final PluginType<?> type : plugins.values()) {
+                final Class<?> pluginClass = type.getPluginClass();
                 try {
                     // Cause the class to be initialized if it isn't already.
-                    Loader.initializeClass(type.getPluginClass().getName(), type.getPluginClass().getClassLoader());
+                    Class.forName(pluginClass.getName(), true, pluginClass.getClassLoader());
                 } catch (final Exception e) {
-                    LOGGER.error("Unable to initialize {} due to {}", type.getPluginClass().getName(), e.getClass()
+                    LOGGER.error("Unable to initialize {} due to {}", pluginClass.getName(), e.getClass()
                             .getSimpleName(), e);
                 }
             }
@@ -292,7 +299,14 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
     private void monitorSource(final Reconfigurable reconfigurable, final ConfigurationSource configSource) {
         if (configSource.getLastModified() > 0) {
             final Source cfgSource = new Source(configSource);
-            final Watcher watcher = WatcherFactory.getInstance(pluginPackages)
+            final Key<WatcherFactory> key = Key.forClass(WatcherFactory.class);
+            injector.registerBindingIfAbsent(key, new LazyValue<>(() -> {
+                final PluginManager pluginManager = injector.getInstance(Watcher.PLUGIN_MANAGER_KEY);
+                pluginManager.collectPlugins(pluginPackages);
+                final Map<String, PluginType<?>> watcherPlugins = pluginManager.getPlugins();
+                return new WatcherFactory(watcherPlugins);
+            }));
+            final Watcher watcher = injector.getInstance(key)
                     .newWatcher(cfgSource, this, reconfigurable, listeners, configSource.getLastModified());
             if (watcher != null) {
                 watchManager.watch(cfgSource, watcher);
@@ -638,7 +652,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         } else {
             final Map<String, String> map = this.getComponent(CONTEXT_PROPERTIES);
             final StrLookup lookup = map == null ? null : new PropertiesLookup(map);
-            Interpolator interpolator = new Interpolator(lookup, pluginPackages);
+            Interpolator interpolator = new Interpolator(lookup, this);
             runtimeStrSubstitutor.setVariableResolver(interpolator);
             configurationStrSubstitutor.setVariableResolver(interpolator);
         }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java
index d027831..94fede4 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java
@@ -16,10 +16,6 @@
  */
 package org.apache.logging.log4j.core.config;
 
-import java.util.HashMap;
-import java.util.Map;
-
-
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.core.lookup.Interpolator;
 import org.apache.logging.log4j.core.lookup.PropertiesLookup;
@@ -29,6 +25,9 @@ import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Handles properties defined in the configuration.
  */
@@ -47,15 +46,16 @@ public final class PropertiesPlugin {
     @PluginFactory
     public static StrLookup configureSubstitutor(@PluginElement("Properties") final Property[] properties,
                                                  @PluginConfiguration final Configuration config) {
+        final Map<String, String> map;
         if (properties == null) {
-            return new Interpolator(config.getProperties());
-        }
-        final Map<String, String> map = new HashMap<>(config.getProperties());
+            map = config.getProperties();
+        } else {
+            map = new HashMap<>(config.getProperties());
 
-        for (final Property prop : properties) {
-            map.put(prop.getName(), prop.getValue());
+            for (final Property prop : properties) {
+                map.put(prop.getName(), prop.getValue());
+            }
         }
-
-        return new Interpolator(new PropertiesLookup(map), config.getPluginPackages());
+        return new Interpolator(new PropertiesLookup(map), config);
     }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
index de48103..f05fa46 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
@@ -16,20 +16,21 @@
  */
 package org.apache.logging.log4j.core.lookup;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationAware;
 import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.util.ReflectionUtil;
+import org.apache.logging.log4j.plugins.di.Key;
 import org.apache.logging.log4j.plugins.util.PluginManager;
 import org.apache.logging.log4j.plugins.util.PluginType;
 import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.ReflectionUtil;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 
 /**
  * Proxies other {@link StrLookup}s using a keys within ${} markers.
@@ -53,19 +54,14 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
 
     private static final Logger LOGGER = StatusLogger.getLogger();
 
-    private static final String JMX_LOOKUP = "org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup";
     private static final String JNDI_LOOKUP = "org.apache.logging.log4j.jndi.lookup.JndiLookup";
-    private static final String WEB_LOOKUP = "org.apache.logging.log4j.web.WebLookup";
-    private static final String DOCKER_LOOKUP = "org.apache.logging.log4j.docker.DockerLookup";
-    private static final String SPRING_LOOKUP = "org.apache.logging.log4j.spring.boot.SpringLookup";
-    private static final String KUBERNETES_LOOKUP = "org.apache.logging.log4j.kubernetes.KubernetesLookup";
 
     private final Map<String, StrLookup> strLookupMap = new HashMap<>();
 
     private final StrLookup defaultLookup;
 
     public Interpolator(final StrLookup defaultLookup) {
-        this(defaultLookup, null);
+        this(defaultLookup, List.of());
     }
 
     /**
@@ -76,7 +72,7 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
      * @since 2.1
      */
     public Interpolator(final StrLookup defaultLookup, final List<String> pluginPackages) {
-        this.defaultLookup = defaultLookup == null ? new PropertiesLookup(new HashMap<String, String>()) : defaultLookup;
+        this.defaultLookup = defaultLookup == null ? new PropertiesLookup(Map.of()) : defaultLookup;
         final PluginManager manager = new PluginManager(CATEGORY);
         manager.collectPlugins(pluginPackages);
         final Map<String, PluginType<?>> plugins = manager.getPlugins();
@@ -93,18 +89,35 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
         }
     }
 
+    public Interpolator(final StrLookup defaultLookup, final Configuration configuration) {
+        this.defaultLookup = defaultLookup == null ? new PropertiesLookup(Map.of()) : defaultLookup;
+        final PluginManager pluginManager = configuration.getComponent(StrLookup.PLUGIN_MANAGER_KEY);
+        pluginManager.collectPlugins(configuration.getPluginPackages());
+        for (final Map.Entry<String, PluginType<?>> entry : pluginManager.getPlugins().entrySet()) {
+            try {
+                final Class<? extends StrLookup> strLookupClass = entry.getValue().getPluginClass().asSubclass(StrLookup.class);
+                // TODO: this could use @RequiredProperty on JndiLookup instead
+                if (!strLookupClass.getName().equals(JNDI_LOOKUP) || Constants.JNDI_LOOKUP_ENABLED) {
+                    strLookupMap.put(entry.getKey().toLowerCase(Locale.ROOT), configuration.getComponent(Key.forClass(strLookupClass)));
+                }
+            } catch (final Throwable t) {
+                handleError(entry.getKey(), t);
+            }
+        }
+    }
+
     /**
      * Create the default Interpolator.
      */
     public Interpolator() {
-        this((Map<String, String>) null);
+        this(Map.of());
     }
 
     /**
      * Creates the default Interpolator with the provided properties.
      */
     public Interpolator(final Map<String, String> properties) {
-        this(new PropertiesLookup(properties), Collections.emptyList());
+        this(new PropertiesLookup(properties), List.of());
     }
 
     public StrLookup getDefaultLookup() {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java
index cdef668..5ef6886 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java
@@ -17,6 +17,9 @@
 package org.apache.logging.log4j.core.lookup;
 
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.plugins.Named;
+import org.apache.logging.log4j.plugins.di.Key;
+import org.apache.logging.log4j.plugins.util.PluginManager;
 
 /**
  * Lookup a String key to a String value.
@@ -39,6 +42,8 @@ public interface StrLookup {
      */
     String CATEGORY = "Lookup";
 
+    Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+
     /**
      * Looks up a String key to a String value.
      * <p>
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
index f3f182f..4cbed02 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
@@ -16,15 +16,15 @@
  */
 package org.apache.logging.log4j.core.util;
 
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.LoaderUtil;
 import org.apache.logging.log4j.util.PropertiesUtil;
 
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+
 /**
  * Load resources (or images) from various sources.
  */
@@ -192,19 +192,6 @@ public final class Loader {
     }
 
     /**
-     * Loads and initializes a named Class using a given ClassLoader.
-     *
-     * @param className The class name.
-     * @param loader The class loader.
-     * @return The class.
-     * @throws ClassNotFoundException if the class could not be found.
-     */
-    public static Class<?> initializeClass(final String className, final ClassLoader loader)
-            throws ClassNotFoundException {
-        return Class.forName(className, true, loader);
-    }
-
-    /**
      * Loads a named Class using a given ClassLoader.
      *
      * @param className The class name.
@@ -270,33 +257,6 @@ public final class Loader {
     }
 
     /**
-     * Loads and instantiates a class given by a property name.
-     *
-     * @param propertyName The property name to look up a class name for.
-     * @param clazz        The class to cast it to.
-     * @param <T>          The type to cast it to.
-     * @return new instance of the class given in the property or {@code null} if the property was unset.
-     * @throws ClassNotFoundException    if the class isn't available to the usual ClassLoaders
-     * @throws IllegalAccessException    if the class can't be instantiated through a public constructor
-     * @throws InstantiationException    if there was an exception whilst instantiating the class
-     * @throws NoSuchMethodException     if there isn't a no-args constructor on the class
-     * @throws InvocationTargetException if there was an exception whilst constructing the class
-     * @throws ClassCastException        if the constructed object isn't type compatible with {@code T}
-     */
-    public static <T> T newCheckedInstanceOfProperty(final String propertyName, final Class<T> clazz)
-        throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
-        IllegalAccessException {
-        final String className = PropertiesUtil.getProperties().getStringProperty(propertyName);
-        final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
-        try {
-            Thread.currentThread().setContextClassLoader(getClassLoader());
-            return LoaderUtil.newCheckedInstanceOfProperty(propertyName, clazz);
-        } finally {
-            Thread.currentThread().setContextClassLoader(contextClassLoader);
-        }
-    }
-
-    /**
      * Loads and instantiates a Class using the default constructor.
      *
      * @param clazz The class.
@@ -337,7 +297,7 @@ public final class Loader {
     }
 
     /**
-     * Loads a class by name. This method respects the {@link #IGNORE_TCCL_PROPERTY} Log4j property. If this property is
+     * Loads a class by name. This method respects the {@link LoaderUtil#IGNORE_TCCL_PROPERTY} Log4j property. If this property is
      * specified and set to anything besides {@code false}, then the default ClassLoader will be used.
      *
      * @param className The class name.
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java
index 61552a9..e02bb09 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java
@@ -16,10 +16,13 @@
  */
 package org.apache.logging.log4j.core.util;
 
-import java.util.List;
-
 import org.apache.logging.log4j.core.config.ConfigurationListener;
 import org.apache.logging.log4j.core.config.Reconfigurable;
+import org.apache.logging.log4j.plugins.Named;
+import org.apache.logging.log4j.plugins.di.Key;
+import org.apache.logging.log4j.plugins.util.PluginManager;
+
+import java.util.List;
 
 /**
  * Watches for changes in a Source and performs an action when it is modified.
@@ -29,6 +32,7 @@ import org.apache.logging.log4j.core.config.Reconfigurable;
 public interface Watcher {
 
     String CATEGORY = "Watcher";
+    Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
     String ELEMENT_TYPE = "watcher";
 
     /**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java
index cd4ec28..343815c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java
@@ -16,47 +16,31 @@
  */
 package org.apache.logging.log4j.core.util;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationFileWatcher;
 import org.apache.logging.log4j.core.config.ConfigurationListener;
 import org.apache.logging.log4j.core.config.Reconfigurable;
-import org.apache.logging.log4j.plugins.util.PluginManager;
 import org.apache.logging.log4j.plugins.util.PluginType;
 import org.apache.logging.log4j.status.StatusLogger;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
 /**
  * Creates Watchers of various types.
  */
 public class WatcherFactory {
 
     private static final Logger LOGGER = StatusLogger.getLogger();
-    private static final PluginManager pluginManager = new PluginManager(Watcher.CATEGORY);
-
-    private static volatile WatcherFactory factory;
 
     private final Map<String, PluginType<?>> plugins;
 
-    private WatcherFactory(final List<String> packages) {
-        pluginManager.collectPlugins(packages);
-        plugins = pluginManager.getPlugins();
-    }
-
-    public static WatcherFactory getInstance(final List<String> packages) {
-        if (factory == null) {
-            synchronized (pluginManager) {
-                if (factory == null) {
-                    factory = new WatcherFactory(packages);
-                }
-            }
-        }
-        return factory;
+    public WatcherFactory(final Map<String, PluginType<?>> watcherPlugins) {
+        plugins = watcherPlugins;
     }
 
     public Watcher newWatcher(final Source source, final Configuration configuration, final Reconfigurable reconfigurable,
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java
index 1fe03a6..2a58724 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java
@@ -20,6 +20,7 @@ package org.apache.logging.log4j.plugins.di;
 
 import org.apache.logging.log4j.plugins.util.TypeUtil;
 
+import java.util.Collection;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Supplier;
@@ -35,8 +36,17 @@ class BindingMap {
         this.bindings = new ConcurrentHashMap<>(bindings.bindings);
     }
 
-    public <T> Binding<T> get(final Key<T> key) {
-        return TypeUtil.cast(bindings.get(key));
+    public <T> Binding<T> get(final Key<T> key, final Collection<String> aliases) {
+        var binding = bindings.get(key);
+        if (binding == null) {
+            for (final String alias : aliases) {
+                binding = bindings.get(key.withName(alias));
+                if (binding != null) {
+                    break;
+                }
+            }
+        }
+        return TypeUtil.cast(binding);
     }
 
     public <T> void put(final Key<T> key, final Supplier<T> factory) {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index 7b70c8a..51bf172 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -20,6 +20,7 @@ package org.apache.logging.log4j.plugins.di;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.plugins.FactoryType;
 import org.apache.logging.log4j.plugins.Inject;
+import org.apache.logging.log4j.plugins.Named;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.PluginException;
 import org.apache.logging.log4j.plugins.QualifierType;
@@ -28,6 +29,7 @@ import org.apache.logging.log4j.plugins.Singleton;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
 import org.apache.logging.log4j.plugins.util.AnnotationUtil;
+import org.apache.logging.log4j.plugins.util.PluginManager;
 import org.apache.logging.log4j.plugins.util.PluginType;
 import org.apache.logging.log4j.plugins.util.TypeUtil;
 import org.apache.logging.log4j.plugins.validation.Constraint;
@@ -192,15 +194,16 @@ class DefaultInjector implements Injector {
 
     private <T> Supplier<T> getFactory(
             final Key<T> key, final Collection<String> aliases, final Node node, final Set<Key<?>> chain) {
-        final Binding<T> existing = bindingMap.get(key);
+        final Binding<T> existing = bindingMap.get(key, aliases);
         if (existing != null) {
             return existing.getSupplier();
         }
-        for (final String alias : aliases) {
-            final Binding<T> binding = bindingMap.get(key.withName(alias));
-            if (binding != null) {
-                return binding.getSupplier();
-            }
+        final Class<T> rawType = key.getRawType();
+        final Scope scope = getScopeForType(rawType);
+        if (rawType == PluginManager.class && key.getQualifierType() == Named.class) {
+            final Supplier<T> factory = () -> TypeUtil.cast(new PluginManager(key.getName()));
+            bindingMap.put(key, scope.get(key, factory));
+            return bindingMap.get(key, aliases).getSupplier();
         }
         final Supplier<T> instanceSupplier = () -> {
             final StringBuilder debugLog = new StringBuilder();
@@ -208,7 +211,6 @@ class DefaultInjector implements Injector {
             injectMembers(key, node, instance, chain, debugLog);
             return instance;
         };
-        final Scope scope = getScopeForType(key.getRawType());
         return bindingMap.bindIfAbsent(key, scope.get(key, instanceSupplier));
     }
 
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java
index 6c4bfc5..8368660 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java
@@ -77,6 +77,10 @@ public class Key<T> {
         hashCode = Objects.hash(type, qualifierType, name.toLowerCase(Locale.ROOT));
     }
 
+    public Type getType() {
+        return type;
+    }
+
     public final Class<T> getRawType() {
         return rawType;
     }
@@ -85,6 +89,10 @@ public class Key<T> {
         return name;
     }
 
+    public Class<? extends Annotation> getQualifierType() {
+        return qualifierType;
+    }
+
     /**
      * Returns a new key using the provided name and the same type and qualifier type as this instance.
      */
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginManager.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginManager.java
index b87e5a1..8360515 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginManager.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginManager.java
@@ -18,15 +18,21 @@
 package org.apache.logging.log4j.plugins.util;
 
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.plugins.Singleton;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.Strings;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * Loads and manages all the plugins.
  */
+@Singleton
 public class PluginManager {
 
     /**

[logging-log4j2] 02/02: Revert MethodHandle usage back to reflection

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit fdd78e9a50b7566c6a4e1b70be1e62708dd517ad
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Tue Mar 22 22:42:47 2022 -0500

    Revert MethodHandle usage back to reflection
    
    The access rules seem a bit too difficult to work around in Java 17.
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../log4j/core/config/LoggersPluginTest.java       |   2 +-
 .../logging/log4j/core/impl/DefaultCallback.java   |   3 +-
 .../log4j/plugin/processor/PluginProcessor.java    |   9 -
 .../logging/log4j/plugins/di/InjectorTest.java     |   3 +-
 .../logging/log4j/plugins/di/DefaultInjector.java  | 189 +++++++++++----------
 .../logging/log4j/plugins/di/InjectException.java  |  30 ++++
 .../apache/logging/log4j/plugins/di/Injector.java  |  11 +-
 .../log4j/plugins/di/ReflectionAccessor.java       |  25 +++
 .../log4j/plugins/processor/PluginService.java     |   5 +-
 .../logging/log4j/plugins/util/PluginRegistry.java |   3 +-
 .../logging/log4j/plugins/util/PluginType.java     |  27 +--
 11 files changed, 164 insertions(+), 143 deletions(-)

diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java
index 4a2df35..5108210 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggersPluginTest.java
@@ -43,6 +43,6 @@ public class LoggersPluginTest {
         //System.out.println(data.getFormattedStatus());
 
         assertThat(data.getLevel()).isEqualTo(Level.ERROR);
-        assertThat(data.getMessage().getFormattedMessage()).contains("multiple root loggers");
+        assertThat(data.getMessage().getFormattedMessage()).startsWith("Could not configure plugin element Loggers");
     }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
index 5940303..1233ab9 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
@@ -45,7 +45,6 @@ import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.PropertiesUtil;
 
-import java.lang.invoke.MethodHandles;
 import java.util.Map;
 import java.util.function.Supplier;
 
@@ -81,7 +80,7 @@ public class DefaultCallback implements InjectorCallback {
     public void configure(final Injector injector) {
         final PropertiesUtil properties = PropertiesUtil.getProperties();
         final var loader = new PropertyLoader(injector, properties, Loader.getClassLoader());
-        injector.setLookup(MethodHandles.lookup());
+        injector.setReflectionAccessor(object -> object.setAccessible(true));
         injector.registerBindingIfAbsent(ContextSelector.KEY,
                         () -> loader.getInstance(Constants.LOG4J_CONTEXT_SELECTOR, ContextSelector.class,
                                 () -> ClassLoaderContextSelector.class))
diff --git a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
index f0e1911..cf6a7a6 100644
--- a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
+++ b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
@@ -156,18 +156,11 @@ public class PluginProcessor extends AbstractProcessor {
         try (final PrintWriter writer = createSourceFile(fqcn)) {
             writer.println("package " + pkg + ".plugins;");
             writer.println("");
-            writer.println("import org.apache.logging.log4j.plugins.di.LookupSelector;");
             writer.println("import org.apache.logging.log4j.plugins.processor.PluginEntry;");
             writer.println("import org.apache.logging.log4j.plugins.processor.PluginService;");
             writer.println("");
-            writer.println("import java.lang.invoke.MethodHandles.Lookup;");
-            writer.println("");
-            writer.println("import static java.lang.invoke.MethodHandles.lookup;");
-            writer.println("import static java.lang.invoke.MethodHandles.privateLookupIn;");
-            writer.println("");
             writer.println("public class Log4jPlugins extends PluginService {");
             writer.println("");
-            writer.println("    private static final Lookup LOOKUP = lookup();");
             writer.println("    private static final PluginEntry[] ENTRIES = new PluginEntry[] {");
             StringBuilder sb = new StringBuilder();
             int max = list.size() - 1;
@@ -189,8 +182,6 @@ public class PluginProcessor extends AbstractProcessor {
             writer.println("    };");
             writer.println("    @Override");
             writer.println("    public PluginEntry[] getEntries() { return ENTRIES; }");
-            writer.println("    @Override");
-            writer.println("    protected LookupSelector getLookupSelector() { return clazz -> privateLookupIn(clazz, LOOKUP); }");
             writer.println("}");
         }
     }
diff --git a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java
index 654439b..8f93480 100644
--- a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java
+++ b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/di/InjectorTest.java
@@ -41,7 +41,6 @@ import org.junit.jupiter.api.parallel.Resources;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.lang.invoke.MethodHandles;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -589,7 +588,7 @@ class InjectorTest {
         final Plugin plugin = clazz.getAnnotation(Plugin.class);
         final PluginEntry entry = new PluginEntry(plugin.name().toLowerCase(Locale.ROOT), clazz.getName(), plugin.name(),
                 plugin.printObject(), plugin.deferChildren(), plugin.category());
-        return new PluginType<>(entry, clazz, MethodHandles.lookup().in(clazz), plugin.elementType());
+        return new PluginType<>(entry, clazz, plugin.elementType());
     }
 
     @Test
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index 51bf172..d7050d2 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -22,7 +22,6 @@ import org.apache.logging.log4j.plugins.FactoryType;
 import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.Named;
 import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.PluginException;
 import org.apache.logging.log4j.plugins.QualifierType;
 import org.apache.logging.log4j.plugins.ScopeType;
 import org.apache.logging.log4j.plugins.Singleton;
@@ -42,14 +41,13 @@ import org.apache.logging.log4j.util.ServiceRegistry;
 import org.apache.logging.log4j.util.StringBuilders;
 
 import java.lang.annotation.Annotation;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.VarHandle;
+import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Parameter;
@@ -75,7 +73,7 @@ class DefaultInjector implements Injector {
 
     private final BindingMap bindingMap;
     private final Map<Class<? extends Annotation>, Scope> scopes = new ConcurrentHashMap<>();
-    private Lookup lookup = MethodHandles.lookup();
+    private ReflectionAccessor accessor = object -> object.setAccessible(true);
 
     DefaultInjector() {
         bindingMap = new BindingMap();
@@ -86,7 +84,7 @@ class DefaultInjector implements Injector {
     DefaultInjector(final DefaultInjector original) {
         bindingMap = new BindingMap(original.bindingMap);
         scopes.putAll(original.scopes);
-        lookup = original.lookup;
+        accessor = original.accessor;
     }
 
     @Override
@@ -170,8 +168,15 @@ class DefaultInjector implements Injector {
     }
 
     @Override
-    public void setLookup(final Lookup lookup) {
-        this.lookup = lookup;
+    public void setReflectionAccessor(final ReflectionAccessor accessor) {
+        this.accessor = accessor;
+    }
+
+    private <M extends AccessibleObject & Member> void makeAccessible(final M member, final Object instance) {
+        final boolean isStatic = Modifier.isStatic(member.getModifiers());
+        if (!member.canAccess(isStatic ? null : instance)) {
+            accessor.makeAccessible(member);
+        }
     }
 
     private <T> Supplier<T> getFactory(
@@ -219,10 +224,10 @@ class DefaultInjector implements Injector {
         final Class<?> rawType = key.getRawType();
         validate(rawType, key.getName(), rawType);
         final Constructor<?> constructor = getInjectableConstructor(key, chain);
+        makeAccessible(constructor, null);
         final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(constructor);
-        final MethodHandle handle = getConstructorHandle(constructor, lookup);
         final var args = getArguments(key, node, points, chain, debugLog);
-        return rethrow(() -> handle.invokeWithArguments(args));
+        return newInstance(constructor, args);
     }
 
     private void validate(final AnnotatedElement element, final String name, final Object value) {
@@ -260,17 +265,16 @@ class DefaultInjector implements Injector {
     }
 
     private <T> void injectField(final Field field, final Node node, final Object instance, final StringBuilder debugLog) {
-        final Lookup fieldLookup = node != null ? node.getType().getPluginLookup() : lookup.in(instance.getClass());
-        final VarHandle handle = getFieldHandle(field, fieldLookup);
+        makeAccessible(field, instance);
         final InjectionPoint<T> point = InjectionPoint.forField(field);
         final Supplier<T> factory = getFactory(point, node, Set.of(), debugLog);
         final Key<T> key = point.getKey();
         final Object value = key.getRawType() == Supplier.class ? factory : factory.get();
         if (value != null) {
-            handle.set(instance, value);
+            setField(field, instance, value);
         }
         if (AnnotationUtil.isMetaAnnotationPresent(field, Constraint.class)) {
-            final Object fieldValue = handle.get(instance);
+            final Object fieldValue = getField(field, instance);
             validate(field, key.getName(), fieldValue);
         }
     }
@@ -278,23 +282,22 @@ class DefaultInjector implements Injector {
     private void injectMethods(
             final Key<?> key, final Node node, final Object instance, final Set<Key<?>> chain, final StringBuilder debugLog) {
         final Class<?> rawType = key.getRawType();
-        final Lookup methodLookup = node != null ? node.getType().getPluginLookup() : lookup.in(instance.getClass());
-        final List<MethodHandle> injectMethodsWithNoArgs = new ArrayList<>();
+        final List<Method> injectMethodsWithNoArgs = new ArrayList<>();
         for (Class<?> clazz = rawType; clazz != Object.class; clazz = clazz.getSuperclass()) {
             for (final Method method : clazz.getDeclaredMethods()) {
                 if (isInjectable(method)) {
-                    final MethodHandle handle = getMethodHandle(method, methodLookup).bindTo(instance);
+                    makeAccessible(method, instance);
                     if (method.getParameterCount() == 0) {
-                        injectMethodsWithNoArgs.add(handle);
+                        injectMethodsWithNoArgs.add(method);
                     } else {
                         final List<InjectionPoint<?>> injectionPoints = InjectionPoint.fromExecutable(method);
-                        final List<?> args = getArguments(key, node, injectionPoints, chain, debugLog);
-                        rethrow(() -> handle.invokeWithArguments(args));
+                        final var args = getArguments(key, node, injectionPoints, chain, debugLog);
+                        invokeMethod(method, instance, args);
                     }
                 }
             }
         }
-        injectMethodsWithNoArgs.forEach(handle -> rethrow(handle::invoke));
+        injectMethodsWithNoArgs.forEach(method -> invokeMethod(method, instance));
     }
 
     private void inject(final Node node) {
@@ -354,15 +357,15 @@ class DefaultInjector implements Injector {
                 .map(Executable.class::cast)
                 .orElseGet(() -> getInjectableConstructor(key, Set.of()));
         final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(factory);
-        final Lookup pluginLookup = type.getPluginLookup();
-        final MethodHandle handle;
+        if (!factory.canAccess(null)) {
+            accessor.makeAccessible(factory);
+        }
+        final var args = getArguments(key, node, points, Set.of(), debugLog);
         if (factory instanceof Method) {
-            handle = getMethodHandle((Method) factory, pluginLookup);
+            return invokeMethod((Method) factory, null, args);
         } else {
-            handle = getConstructorHandle((Constructor<?>) factory, pluginLookup);
+            return newInstance((Constructor<?>) factory, args);
         }
-        final var args = getArguments(key, node, points, Set.of(), debugLog);
-        return rethrow(() -> handle.invokeWithArguments(args));
     }
 
     private void registerModuleInstance(final Object module) {
@@ -379,7 +382,7 @@ class DefaultInjector implements Injector {
                         createMethodBindings(module, method).forEach(binding -> {
                             final var key = binding.getKey();
                             if (!bindingMap.putIfAbsent(key, binding.getSupplier())) {
-                                throw new PluginException(String.format(
+                                throw new InjectException(String.format(
                                         "Duplicate @Factory method (%s: %s) found for %s", moduleClass, method, key));
                             }
                         });
@@ -388,20 +391,22 @@ class DefaultInjector implements Injector {
     }
 
     private <T> List<Binding<T>> createMethodBindings(final Object instance, final Method method) {
+        makeAccessible(method, instance);
         final Key<T> primaryKey = Key.forMethod(method);
         final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(method);
-        final MethodHandle handle = getMethodHandle(method, lookup);
-        final MethodHandle boundHandle = Modifier.isStatic(method.getModifiers()) ? handle : handle.bindTo(instance);
         final var argumentFactories = getArgumentFactories(primaryKey, null, points, Set.of(primaryKey), null);
         final Supplier<T> unscoped = () -> {
-            final List<Object> args = argumentFactories.entrySet()
+            final var args = argumentFactories.entrySet()
                     .stream()
-                    .flatMap(e -> {
+                    .map(e -> {
+                        final Parameter parameter = e.getKey();
+                        final String name = AnnotatedElementNameProvider.getName(parameter);
                         final Object value = e.getValue().get();
-                        return e.getKey().isVarArgs() ? Stream.of((Object[]) value) : Stream.of(value);
+                        validate(parameter, name, value);
+                        return value;
                     })
-                    .collect(Collectors.toList());
-            return TypeUtil.cast(rethrow(() -> boundHandle.invokeWithArguments(args)));
+                    .toArray();
+            return rethrow(() -> TypeUtil.cast(invokeMethod(method, instance, args)));
         };
         final Supplier<T> factory = getScopeForMethod(method).get(primaryKey, unscoped);
         final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(method);
@@ -413,20 +418,20 @@ class DefaultInjector implements Injector {
         return bindings;
     }
 
-    private List<Object> getArguments(
+    private Object[] getArguments(
             final Key<?> key, final Node node, final List<InjectionPoint<?>> points, final Set<Key<?>> chain,
             final StringBuilder debugLog) {
         return getArgumentFactories(key, node, points, chain, debugLog)
                 .entrySet()
                 .stream()
-                .flatMap(e -> {
+                .map(e -> {
                     final Parameter parameter = e.getKey();
                     final String name = AnnotatedElementNameProvider.getName(parameter);
                     final Object value = e.getValue().get();
                     validate(parameter, name, value);
-                    return parameter.isVarArgs() ? Stream.of((Object[]) value) : Stream.of(value);
+                    return value;
                 })
-                .collect(Collectors.toList());
+                .toArray();
     }
 
     private Map<Parameter, Supplier<?>> getArgumentFactories(
@@ -446,7 +451,7 @@ class DefaultInjector implements Injector {
                         sb.append(chainKey).append(" -> ");
                     }
                     sb.append(parameterKey);
-                    throw new PluginException(sb.toString());
+                    throw new InjectException(sb.toString());
                 }
                 argFactories.put(parameter, () -> getFactory(point, node, newChain, debugLog).get());
             }
@@ -464,7 +469,8 @@ class DefaultInjector implements Injector {
         return scope != null ? scopes.get(scope.annotationType()) : DefaultScope.INSTANCE;
     }
 
-    private static boolean isCompatibleValidator(final Constraint constraint, final Class<? extends Annotation> annotationType) {
+    private static boolean isCompatibleValidator(
+            final Constraint constraint, final Class<? extends Annotation> annotationType) {
         for (final Type type : constraint.value().getGenericInterfaces()) {
             if (type instanceof ParameterizedType) {
                 ParameterizedType parameterizedType = (ParameterizedType) type;
@@ -478,7 +484,8 @@ class DefaultInjector implements Injector {
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private static void initializeConstraintValidator(final ConstraintValidator<? extends Annotation> validator, final Annotation annotation) {
+    private static void initializeConstraintValidator(
+            final ConstraintValidator<? extends Annotation> validator, final Annotation annotation) {
         // runtime type checking ensures this raw type usage is correct
         ((ConstraintValidator) validator).initialize(annotation);
     }
@@ -525,61 +532,13 @@ class DefaultInjector implements Injector {
         return newChain;
     }
 
-    private static VarHandle getFieldHandle(final Field field, final Lookup lookup) {
-        final Class<?> declaringClass = field.getDeclaringClass();
-        try {
-            return lookup.unreflectVarHandle(field);
-        } catch (final IllegalAccessException outer) {
-            try {
-                return MethodHandles.privateLookupIn(declaringClass, lookup).unreflectVarHandle(field);
-            } catch (final IllegalAccessException inner) {
-                final var error = new IllegalAccessError("Cannot access field " + field);
-                error.addSuppressed(inner);
-                error.addSuppressed(outer);
-                throw error;
-            }
-        }
-    }
-
-    private static MethodHandle getMethodHandle(final Method method, final Lookup lookup) {
-        final Class<?> declaringClass = method.getDeclaringClass();
-        try {
-            return lookup.unreflect(method);
-        } catch (final IllegalAccessException outer) {
-            try {
-                return MethodHandles.privateLookupIn(declaringClass, lookup).unreflect(method);
-            } catch (final IllegalAccessException inner) {
-                final var error = new IllegalAccessError("Cannot access method " + method);
-                error.addSuppressed(inner);
-                error.addSuppressed(outer);
-                throw error;
-            }
-        }
-    }
-
-    private static MethodHandle getConstructorHandle(final Constructor<?> constructor, final Lookup lookup) {
-        final Class<?> declaringClass = constructor.getDeclaringClass();
-        try {
-            return lookup.unreflectConstructor(constructor);
-        } catch (final IllegalAccessException outer) {
-            try {
-                return MethodHandles.privateLookupIn(declaringClass, lookup).unreflectConstructor(constructor);
-            } catch (final IllegalAccessException inner) {
-                final var error = new IllegalAccessError("Cannot access constructor " + constructor);
-                error.addSuppressed(inner);
-                error.addSuppressed(outer);
-                throw error;
-            }
-        }
-    }
-
     private static <T> Constructor<T> getInjectableConstructor(final Key<T> key, final Set<Key<?>> chain) {
         final Class<T> rawType = key.getRawType();
         final List<Constructor<?>> injectConstructors = Stream.of(rawType.getDeclaredConstructors())
                 .filter(constructor -> constructor.isAnnotationPresent(Inject.class))
                 .collect(Collectors.toList());
         if (injectConstructors.size() > 1) {
-            throw new PluginException("Multiple @Inject constructors found in " + rawType);
+            throw new InjectException("Multiple @Inject constructors found in " + rawType);
         }
         if (injectConstructors.size() == 1) {
             return TypeUtil.cast(injectConstructors.get(0));
@@ -597,7 +556,7 @@ class DefaultInjector implements Injector {
         final String prefix = chain.isEmpty() ? "" : "chain ";
         final String keysToString =
                 prefix + keys.stream().map(Key::toString).collect(Collectors.joining(" -> "));
-        throw new PluginException(
+        throw new InjectException(
                 "No @Inject constructors or no-arg constructor found for " + keysToString);
     }
 
@@ -612,6 +571,50 @@ class DefaultInjector implements Injector {
                                 parameter -> AnnotationUtil.isMetaAnnotationPresent(parameter, QualifierType.class));
     }
 
+    private static Object getField(final Field field, final Object instance) {
+        try {
+            return field.get(instance);
+        } catch (final IllegalAccessException e) {
+            throw errorFrom(e);
+        }
+    }
+
+    private static void setField(final Field field, final Object instance, final Object value) {
+        try {
+            field.set(instance, value);
+        } catch (final IllegalAccessException e) {
+            throw errorFrom(e);
+        }
+    }
+
+    private static Object invokeMethod(final Method method, final Object instance, final Object... args) {
+        try {
+            return method.invoke(instance, args);
+        } catch (final InvocationTargetException e) {
+            throw new InjectException(e.getMessage(), e.getCause());
+        } catch (final IllegalAccessException e) {
+            throw errorFrom(e);
+        }
+    }
+
+    private static <T> T newInstance(final Constructor<T> constructor, final Object[] args) {
+        try {
+            return constructor.newInstance(args);
+        } catch (final InvocationTargetException e) {
+            throw new InjectException(e.getMessage(), e.getCause());
+        } catch (final IllegalAccessException e) {
+            throw errorFrom(e);
+        } catch (final InstantiationException e) {
+            throw new InjectException(e.getMessage(), e);
+        }
+    }
+
+    private static IllegalAccessError errorFrom(final IllegalAccessException e) {
+        final IllegalAccessError error = new IllegalAccessError(e.getMessage());
+        error.initCause(e);
+        return error;
+    }
+
     private static <T> T rethrow(final CheckedSupplier<T> supplier) {
         try {
             return supplier.get();
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/InjectException.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/InjectException.java
new file mode 100644
index 0000000..7913745
--- /dev/null
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/InjectException.java
@@ -0,0 +1,30 @@
+/*
+ * 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 org.apache.logging.log4j.plugins.di;
+
+import org.apache.logging.log4j.plugins.PluginException;
+
+public class InjectException extends PluginException {
+    public InjectException(final String message) {
+        super(message);
+    }
+
+    public InjectException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
index e5ad184..8420c92 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
@@ -21,7 +21,6 @@ import org.apache.logging.log4j.plugins.FactoryType;
 import org.apache.logging.log4j.plugins.Node;
 
 import java.lang.annotation.Annotation;
-import java.lang.invoke.MethodHandles.Lookup;
 import java.util.function.Supplier;
 
 /**
@@ -149,12 +148,12 @@ public interface Injector {
      */
     <T> Injector registerBindingIfAbsent(final Key<T> key, final Supplier<? extends T> factory);
 
-
     /**
-     * Sets the {@link Lookup} used for obtaining MethodHandle and VarHandle instances. A custom caller class
-     * can invoke {@code setLookup(MethodHandles.lookup())} as a typical use case.
+     * Sets the {@link ReflectionAccessor} used for invoking {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)}
+     * from an appropriate caller class. Customizing this allows for changing the base module that other modules should
+     * open themselves to.
      *
-     * @param lookup handle lookup object for access checks
+     * @param accessor accessor to use
      */
-    void setLookup(final Lookup lookup);
+    void setReflectionAccessor(final ReflectionAccessor accessor);
 }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java
new file mode 100644
index 0000000..22508ce
--- /dev/null
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/ReflectionAccessor.java
@@ -0,0 +1,25 @@
+/*
+ * 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 org.apache.logging.log4j.plugins.di;
+
+import java.lang.reflect.AccessibleObject;
+
+@FunctionalInterface
+public interface ReflectionAccessor {
+    void makeAccessible(final AccessibleObject object);
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
index aa1392d..00d8a7c 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
@@ -16,7 +16,6 @@
  */
 package org.apache.logging.log4j.plugins.processor;
 
-import org.apache.logging.log4j.plugins.di.LookupSelector;
 import org.apache.logging.log4j.plugins.util.PluginType;
 
 import java.util.ArrayList;
@@ -41,15 +40,13 @@ public abstract class PluginService {
         for (PluginEntry entry : entries) {
             String category = entry.getCategory().toLowerCase();
             List<PluginType<?>> list = categories.computeIfAbsent(category, ignored -> new ArrayList<>());
-            PluginType<?> type = new PluginType<>(entry, classLoader, getLookupSelector());
+            PluginType<?> type = new PluginType<>(entry, classLoader);
             list.add(type);
         }
     }
 
     public abstract PluginEntry[] getEntries();
 
-    protected abstract LookupSelector getLookupSelector();
-
     public Map<String, List<PluginType<?>>> getCategories() {
         return Collections.unmodifiableMap(categories);
     }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
index dd3a4ce..413f9e1 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
@@ -253,8 +253,7 @@ public class PluginRegistry {
             newPluginsByCategory.put(categoryLowerCase, types);
             for (final Map.Entry<String, PluginEntry> inner : outer.getValue().entrySet()) {
                 final PluginEntry entry = inner.getValue();
-                final PluginType<?> type = new PluginType<>(entry, context.getClassLoader(),
-                        clazz -> MethodHandles.privateLookupIn(clazz, context.getLookup()));
+                final PluginType<?> type = new PluginType<>(entry, context.getClassLoader());
                 types.add(type);
                 ++pluginCount;
             }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
index 55adbc5..f1ab067 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
@@ -16,12 +16,9 @@
  */
 package org.apache.logging.log4j.plugins.util;
 
-import org.apache.logging.log4j.plugins.di.LookupSelector;
 import org.apache.logging.log4j.plugins.processor.PluginEntry;
 import org.apache.logging.log4j.util.LazyValue;
 
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
 import java.util.function.Supplier;
 
 /**
@@ -34,7 +31,6 @@ public class PluginType<T> {
 
     private final PluginEntry pluginEntry;
     private final Supplier<Class<T>> pluginClass;
-    private final Supplier<Lookup> pluginLookup;
     private final String elementName;
 
     /**
@@ -44,15 +40,10 @@ public class PluginType<T> {
      * @param elementName The name of the element.
      * @since 2.1
      */
-    public PluginType(final PluginEntry pluginEntry, final Class<T> pluginClass, final String elementName) {
-        this(pluginEntry, pluginClass, MethodHandles.lookup().in(pluginClass), elementName);
-    }
-
     public PluginType(
-            final PluginEntry pluginEntry, final Class<T> pluginClass, final Lookup pluginLookup, final String elementName) {
+            final PluginEntry pluginEntry, final Class<T> pluginClass, final String elementName) {
         this.pluginEntry = pluginEntry;
         this.pluginClass = () -> pluginClass;
-        this.pluginLookup = () -> pluginLookup;
         this.elementName = elementName;
     }
 
@@ -61,9 +52,9 @@ public class PluginType<T> {
      * @since 3.0
      * @param pluginEntry The PluginEntry.
      */
-    public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader, final LookupSelector lookupSelector) {
+    public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader) {
         this.pluginEntry = pluginEntry;
-        final LazyValue<Class<T>> pluginClass = new LazyValue<>(() -> {
+        this.pluginClass = new LazyValue<>(() -> {
             try {
                 return TypeUtil.cast(classLoader.loadClass(pluginEntry.getClassName()));
             } catch (final ClassNotFoundException e) {
@@ -71,14 +62,6 @@ public class PluginType<T> {
                         " located for element " + pluginEntry.getName(), e);
             }
         });
-        this.pluginClass = pluginClass;
-        this.pluginLookup = pluginClass.map(clazz -> {
-            try {
-                return lookupSelector.in(clazz);
-            } catch (final IllegalAccessException e) {
-                throw new IllegalAccessError(e.getMessage());
-            }
-        });
         this.elementName = pluginEntry.getName();
     }
 
@@ -91,10 +74,6 @@ public class PluginType<T> {
         return pluginClass.get();
     }
 
-    public Lookup getPluginLookup() {
-        return pluginLookup.get();
-    }
-
     public String getElementName() {
         return this.elementName;
     }