Repository: logging-log4j2
Updated Branches:
  refs/heads/master fe4296a4c -> 5dce32321


[LOG4J2-1764]: Use MethodHandle in ContextDataFactory

When a custom StringMap implementation is specified, the core reflection
API is used. This performs many security access checks on each
invocation. The MethodHandle API only performs a security access check
on construction of the MethodHandle and is also optimized for use with
invokedynamic JVM bytecode instructions.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/5dce3232
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/5dce3232
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/5dce3232

Branch: refs/heads/master
Commit: 5dce323216e1c48035b38ce1f1f825eb0d50b81e
Parents: fe4296a
Author: Matt Sicker <[email protected]>
Authored: Tue Jan 3 22:22:03 2017 -0600
Committer: Matt Sicker <[email protected]>
Committed: Tue Jan 3 22:22:03 2017 -0600

----------------------------------------------------------------------
 .../log4j/core/impl/ContextDataFactory.java     | 45 +++++++++++++-------
 src/changes/changes.xml                         |  5 ++-
 2 files changed, 33 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5dce3232/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataFactory.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataFactory.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataFactory.java
index 410c128..8abc22a 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataFactory.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataFactory.java
@@ -16,7 +16,9 @@
  */
 package org.apache.logging.log4j.core.impl;
 
-import java.lang.reflect.Constructor;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 
 import org.apache.logging.log4j.core.ContextDataInjector;
 import org.apache.logging.log4j.core.LogEvent;
@@ -43,57 +45,68 @@ import org.apache.logging.log4j.util.StringMap;
  * @since 2.7
  */
 public class ContextDataFactory {
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
     private static final String CLASS_NAME = 
PropertiesUtil.getProperties().getStringProperty("log4j2.ContextData");
-    private static final Class<?> CACHED_CLASS = createCachedClass(CLASS_NAME);
-    private static final Constructor<?> CACHED_CONSTRUCTOR = 
createCachedConstructor(CACHED_CLASS);
+    private static final Class<? extends StringMap> CACHED_CLASS = 
createCachedClass(CLASS_NAME);
+    private static final MethodHandle DEFAULT_CONSTRUCTOR = 
createDefaultConstructor(CACHED_CLASS);
+    private static final MethodHandle INITIAL_CAPACITY_CONSTRUCTOR = 
createInitialCapacityConstructor(CACHED_CLASS);
 
     private static final StringMap EMPTY_STRING_MAP = createContextData(1);
     static {
         EMPTY_STRING_MAP.freeze();
     }
 
-    private static Class<?> createCachedClass(final String className) {
+    private static Class<? extends StringMap> createCachedClass(final String 
className) {
         if (className == null) {
             return null;
         }
         try {
-            return LoaderUtil.loadClass(className);
+            return LoaderUtil.loadClass(className).asSubclass(StringMap.class);
         } catch (final Exception any) {
             return null;
         }
     }
 
-    private static Constructor<?> createCachedConstructor(final Class<?> 
cachedClass) {
+    private static MethodHandle createDefaultConstructor(final Class<? extends 
StringMap> cachedClass) {
         if (cachedClass == null) {
             return null;
         }
         try {
-            return cachedClass.getDeclaredConstructor(int.class);
-        } catch (final Exception any) {
+            return LOOKUP.findConstructor(cachedClass, 
MethodType.methodType(void.class));
+        } catch (final NoSuchMethodException | IllegalAccessException ignored) 
{
+            return null;
+        }
+    }
+
+    private static MethodHandle createInitialCapacityConstructor(final Class<? 
extends StringMap> cachedClass) {
+        if (cachedClass == null) {
+            return null;
+        }
+        try {
+            return LOOKUP.findConstructor(cachedClass, 
MethodType.methodType(void.class, int.class));
+        } catch (final NoSuchMethodException | IllegalAccessException ignored) 
{
             return null;
         }
     }
 
-    @SuppressWarnings("unchecked")
     public static StringMap createContextData() {
-        if (CACHED_CLASS == null) {
+        if (DEFAULT_CONSTRUCTOR == null) {
             return new SortedArrayStringMap();
         }
         try {
-            return (StringMap) CACHED_CLASS.newInstance();
-        } catch (final Exception any) {
+            return (StringMap) DEFAULT_CONSTRUCTOR.invoke();
+        } catch (final Throwable ignored) {
             return new SortedArrayStringMap();
         }
     }
 
-    @SuppressWarnings("unchecked")
     public static StringMap createContextData(final int initialCapacity) {
-        if (CACHED_CONSTRUCTOR == null) {
+        if (INITIAL_CAPACITY_CONSTRUCTOR == null) {
             return new SortedArrayStringMap(initialCapacity);
         }
         try {
-            return (StringMap) CACHED_CONSTRUCTOR.newInstance(initialCapacity);
-        } catch (final Exception any) {
+            return (StringMap) 
INITIAL_CAPACITY_CONSTRUCTOR.invoke(initialCapacity);
+        } catch (final Throwable ignored) {
             return new SortedArrayStringMap(initialCapacity);
         }
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5dce3232/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 905f9ae..d7bb884 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -23,7 +23,7 @@
     <title>Changes</title>
   </properties>
   <body>
-    <release version="2.8" date="2016-MM-DD" description="GA Release 2.8">
+    <release version="2.8" date="2017-MM-DD" description="GA Release 2.8">
       <action issue="LOG4J2-1649" dev="rgoers" type="fix" due-to="Georg 
Friedrich">
         Insure the ConfigurationScheduler shuts down without blocking.
       </action>
@@ -222,6 +222,9 @@
       <action issue="LOG4J2-1302" dev="rpopma" type="update">
         The log4j-slf4j-impl module now declares a runtime dependency on 
log4j-core. While not technically required, this makes the log4j-slf4j-impl 
module behave similarly to slf4j-log4j12, and facilitates migration to Log4j 2.
       </action>
+      <action issue="LOG4J2-1764" dev="mattsicker" type="add">
+        Use MethodHandle in ContextDataFactory cached constructor.
+      </action>
       <action issue="LOG4J2-1763" dev="mattsicker" type="add">
         Use MethodHandle instead of Method in ReflectionUtil.
       </action>

Reply via email to