You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2020/03/06 00:31:06 UTC

[logging-log4j2] branch master updated: LOG4J2-2795 - Reduce Log4j 2 initialization time by deferring loading Plugin classes.

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 039ae0b  LOG4J2-2795 - Reduce Log4j 2 initialization time by deferring loading Plugin classes.
039ae0b is described below

commit 039ae0bb7c77b9993a8684b12f0518187001f358
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Thu Mar 5 17:30:53 2020 -0700

    LOG4J2-2795 - Reduce Log4j 2 initialization time by deferring loading Plugin classes.
---
 .../org/apache/logging/log4j/test/GetLogger.java   | 37 ++++++++++++++++++++++
 .../log4j/plugins/processor/PluginEntry.java       | 19 -----------
 .../log4j/plugins/processor/PluginProcessor.java   |  4 +--
 .../log4j/plugins/processor/PluginService.java     |  2 +-
 .../logging/log4j/plugins/util/PluginRegistry.java | 15 +++------
 .../logging/log4j/plugins/util/PluginType.java     | 26 ++++++++++++++-
 src/changes/changes.xml                            |  4 +--
 7 files changed, 71 insertions(+), 36 deletions(-)

diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/test/GetLogger.java b/log4j-core/src/test/java/org/apache/logging/log4j/test/GetLogger.java
new file mode 100644
index 0000000..13015f2
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/test/GetLogger.java
@@ -0,0 +1,37 @@
+/*
+ * 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.test;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+
+/**
+ * Used to profile obtaining a Logger
+ */
+public class GetLogger {
+
+    public static void main(String[] args) {
+        int count = Integer.parseInt(args[0]);
+        LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
+        for (int i = 0; i < count; ++i) {
+            Logger logger = LogManager.getLogger("Logger" + i);
+            logger.debug("This is a test");
+        }
+        System.out.println("Number of Loggers: " + loggerContext.getLoggers().size());
+    }
+}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginEntry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginEntry.java
index dfebe5a..bd452d3 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginEntry.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginEntry.java
@@ -27,7 +27,6 @@ public class PluginEntry implements Serializable {
 
     private String key;
     private String className;
-    private Class<?> pluginClass;
     private String name;
     private boolean printable;
     private boolean defer;
@@ -45,16 +44,6 @@ public class PluginEntry implements Serializable {
         this.category = category;
     }
 
-    public PluginEntry(String key, Class<?> pluginClass, String name, boolean printable, boolean defer, String category) {
-        this.key = key;
-        this.className = pluginClass.getName();
-        this.pluginClass = pluginClass;
-        this.name = name;
-        this.printable = printable;
-        this.defer = defer;
-        this.category = category;
-    }
-
     public String getKey() {
         return key;
     }
@@ -71,14 +60,6 @@ public class PluginEntry implements Serializable {
         this.className = className;
     }
 
-    public Class<?> getPluginClass() {
-        return pluginClass;
-    }
-
-    public void setPluginClass(Class<?> pluginClass) {
-        this.pluginClass = pluginClass;
-    }
-
     public String getName() {
         return name;
     }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginProcessor.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginProcessor.java
index e747ba9..6ccfdd2 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginProcessor.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginProcessor.java
@@ -174,8 +174,8 @@ public class PluginProcessor extends AbstractProcessor {
             for (int i = 0; i < list.size(); ++i) {
                 PluginEntry entry = list.get(i);
                 sb.append("        ").append("new PluginEntry(\"");
-                sb.append(entry.getKey()).append("\", ");
-                sb.append(entry.getClassName().replace('$', '.')).append(".class, \"");
+                sb.append(entry.getKey()).append("\", \"");
+                sb.append(entry.getClassName()).append("\", \"");
                 sb.append(entry.getName()).append("\", ");
                 sb.append(entry.isPrintable()).append(", ");
                 sb.append(entry.isDefer()).append(", \"");
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 0b07093..86c068a 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
@@ -36,7 +36,7 @@ public abstract class PluginService {
         for (PluginEntry entry : entries) {
             String category = entry.getCategory().toLowerCase();
             List<PluginType<?>> list = categories.computeIfAbsent(category, ignored -> new LinkedList<>());
-            PluginType<?> type = new PluginType<>(entry, entry.getPluginClass(), entry.getName());
+            PluginType<?> type = new PluginType<>(entry, this.getClass().getClassLoader());
             list.add(type);
         }
     }
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 f9d3e0a..8a266eb 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
@@ -202,7 +202,7 @@ public class PluginRegistry {
         for (final PluginService pluginService : serviceLoader) {
             PluginEntry[] entries = pluginService.getEntries();
             for (PluginEntry entry : entries) {
-                final PluginType<?> type = new PluginType<>(entry, entry.getPluginClass(), entry.getName());
+                final PluginType<?> type = new PluginType<>(entry, classLoader);
                 String category = entry.getCategory().toLowerCase();
                 if (!map.containsKey(category)) {
                     map.put(category, new ArrayList<>());
@@ -246,16 +246,9 @@ public class PluginRegistry {
             for (final Map.Entry<String, PluginEntry> inner : outer.getValue().entrySet()) {
                 final PluginEntry entry = inner.getValue();
                 final String className = entry.getClassName();
-                try {
-                    final Class<?> clazz = loader.loadClass(className);
-                    final PluginType<?> type = new PluginType<>(entry, clazz, entry.getName());
-                    types.add(type);
-                    ++pluginCount;
-                } catch (final ClassNotFoundException e) {
-                    LOGGER.info("Plugin [{}] could not be loaded due to missing classes.", className, e);
-                } catch (final LinkageError e) {
-                    LOGGER.info("Plugin [{}] could not be loaded due to linkage error.", className, e);
-                }
+                final PluginType<?> type = new PluginType<>(entry, loader);
+                types.add(type);
+                ++pluginCount;
             }
         }
         final int numPlugins = 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 cd3fa49..f2f5008 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
@@ -28,7 +28,8 @@ import org.apache.logging.log4j.plugins.processor.PluginEntry;
 public class PluginType<T> {
 
     private final PluginEntry pluginEntry;
-    private final Class<T> pluginClass;
+    private volatile Class<T> pluginClass;
+    private final ClassLoader classLoader;
     private final String elementName;
 
     /**
@@ -38,13 +39,36 @@ public class PluginType<T> {
         this.pluginEntry = pluginEntry;
         this.pluginClass = pluginClass;
         this.elementName = elementName;
+        this.classLoader = null;
     }
 
+    /**
+     * @since 3.0
+     * @param pluginEntry The PluginEntry.
+     * @param classLoader The ClassLoader to use to load the Plugin.
+     */
+    public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader) {
+        this.pluginEntry = pluginEntry;
+        this.classLoader = classLoader;
+        this.elementName = pluginEntry.getName();
+        this.pluginClass = null;
+    }
+
+
     public PluginEntry getPluginEntry() {
         return this.pluginEntry;
     }
 
+    @SuppressWarnings("unchecked")
     public Class<T> getPluginClass() {
+        if (pluginClass == null) {
+            try {
+                pluginClass = (Class<T>) this.classLoader.loadClass(pluginEntry.getClassName());
+            } catch (ClassNotFoundException | LinkageError ex) {
+                throw new IllegalStateException("No class named " + pluginEntry.getClassName() +
+                        " located for element " + elementName, ex);
+            }
+        }
         return this.pluginClass;
     }
 
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 2c375f5..45b6c38 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,8 +31,8 @@
          - "remove" - Removed
     -->
     <release version="3.0.0" date="2019-xx-xx" description="GA Release 3.0.0">
-      <action issue="LOG4J2-2783" dev="rgoers" type="update">
-        PluginService should use classes in their definition instead of class names.
+      <action issue="LOG4J2-2795" dev="rgoers" type="fix">
+        Reduce Log4j 2 initialization time by deferring loading Plugin classes.
       </action>
       <action issue="LOG4J2-2678" dev="rgoers" type="update" due-to="Federico D'Ambrosio">
         Add LogEvent timestamp to ProducerRecord in KafkaAppender.