Update LoaderUtil.getCurrentStackTrace() to prefer SecurityManager. - Based on benchmarks, it's faster to use SecurityManager when getting the entire stack trace than to use sun.reflect.Reflection
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/599c1f06 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/599c1f06 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/599c1f06 Branch: refs/heads/master Commit: 599c1f06790800721b2b2bb6ad2553199da51dd0 Parents: 415108f Author: Matt Sicker <[email protected]> Authored: Sat Oct 4 10:18:30 2014 -0500 Committer: Matt Sicker <[email protected]> Committed: Sat Oct 4 10:28:14 2014 -0500 ---------------------------------------------------------------------- .../logging/log4j/util/ReflectionUtil.java | 36 ++++++++++---------- .../logging/log4j/util/ReflectionUtilTest.java | 16 +++++---- 2 files changed, 27 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/599c1f06/log4j-api/src/main/java/org/apache/logging/log4j/util/ReflectionUtil.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ReflectionUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ReflectionUtil.java index 3d95e78..89e7a20 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ReflectionUtil.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ReflectionUtil.java @@ -90,19 +90,15 @@ public final class ReflectionUtil { JDK_7u25_OFFSET = java7u25CompensationOffset; PrivateSecurityManager psm; - if (!SUN_REFLECTION_SUPPORTED) { - try { - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("createSecurityManager")); - } - psm = new PrivateSecurityManager(); - } catch (final SecurityException ignored) { - LOGGER.debug( - "Not allowed to create SecurityManager. Falling back to slowest ReflectionUtil implementation."); - psm = null; + try { + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("createSecurityManager")); } - } else { + psm = new PrivateSecurityManager(); + } catch (final SecurityException ignored) { + LOGGER.debug( + "Not allowed to create SecurityManager. Falling back to slowest ReflectionUtil implementation."); psm = null; } SECURITY_MANAGER = psm; @@ -227,17 +223,21 @@ public final class ReflectionUtil { // migrated from ThrowableProxy public static Stack<Class<?>> getCurrentStackTrace() { - if (supportsFastReflection()) { + // benchmarks show that using the SecurityManager is much faster than looping through getCallerClass(int) + if (SECURITY_MANAGER != null) { + final Class<?>[] array = SECURITY_MANAGER.getClassContext(); final Stack<Class<?>> classes = new Stack<Class<?>>(); - Class<?> clazz; - for (int i = 1; null != (clazz = getCallerClass(i)); i++) { + classes.ensureCapacity(array.length); + for (final Class<?> clazz : array) { classes.push(clazz); } return classes; - } else if (SECURITY_MANAGER != null) { - final Class<?>[] array = SECURITY_MANAGER.getClassContext(); + } + // slower version using getCallerClass where we cannot use a SecurityManager + if (supportsFastReflection()) { final Stack<Class<?>> classes = new Stack<Class<?>>(); - for (final Class<?> clazz : array) { + Class<?> clazz; + for (int i = 1; null != (clazz = getCallerClass(i)); i++) { classes.push(clazz); } return classes; http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/599c1f06/log4j-api/src/test/java/org/apache/logging/log4j/util/ReflectionUtilTest.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/util/ReflectionUtilTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/util/ReflectionUtilTest.java index 95fb0ad..0a482bb 100644 --- a/log4j-api/src/test/java/org/apache/logging/log4j/util/ReflectionUtilTest.java +++ b/log4j-api/src/test/java/org/apache/logging/log4j/util/ReflectionUtilTest.java @@ -73,14 +73,16 @@ public class ReflectionUtilTest { @Test public void testGetCurrentStackTrace() throws Exception { final Stack<Class<?>> classes = ReflectionUtil.getCurrentStackTrace(); - Class<?> prev = null; - Class<?> next = null; + final Stack<Class<?>> reversed = new Stack<Class<?>>(); + reversed.ensureCapacity(classes.size()); while (!classes.empty()) { - prev = next; - next = classes.pop(); -// System.out.println(next); + reversed.push(classes.pop()); } - assertSame(ReflectionUtilTest.class, prev); + while (reversed.peek() != ReflectionUtil.class) { + reversed.pop(); + } + reversed.pop(); // ReflectionUtil + assertSame(ReflectionUtilTest.class, reversed.pop()); } @Test @@ -91,4 +93,4 @@ public class ReflectionUtilTest { // update this test accordingly assertSame(expected, actual); } -} \ No newline at end of file +}
