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>
