You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2022/01/08 14:30:25 UTC
[logging-log4j2] 01/02: Add StackLocatorUtil.getCallerClassLoader(int) for the 1.2 bridge.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 6c6b0a20da76453bfdb72f402dc40e5eeda4e5f9
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sat Jan 8 09:30:04 2022 -0500
Add StackLocatorUtil.getCallerClassLoader(int) for the 1.2 bridge.
- Add some Javadocs.
- Fix error message to not mention Java 7 versions.
- Normalize constant name.
- Remove single use local variable.
- Split commit for cherry-picking to master.
---
.../apache/logging/log4j/util/StackLocator.java | 69 ++++++++++++++--------
.../logging/log4j/util/StackLocatorUtil.java | 22 +++++++
2 files changed, 65 insertions(+), 26 deletions(-)
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
index 1e50aa9..495b66f 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
@@ -47,46 +47,50 @@ import java.util.function.Predicate;
*/
public final class StackLocator {
- // Checkstyle Suppress: the lower-case 'u' ticks off CheckStyle...
- // CHECKSTYLE:OFF
- static final int JDK_7u25_OFFSET;
- // CHECKSTYLE:OFF
+ /** TODO Consider removing now that we require Java 8. */
+ static final int JDK_7U25_OFFSET;
- private static final Method GET_CALLER_CLASS;
+ private static final Method GET_CALLER_CLASS_METHOD;
private static final StackLocator INSTANCE;
+
+ /** TODO: Use Object.class. */
+ private static final Class<?> DEFAULT_CALLER_CLASS = null;
static {
- Method getCallerClass;
+ Method getCallerClassMethod;
int java7u25CompensationOffset = 0;
try {
final Class<?> sunReflectionClass = LoaderUtil.loadClass("sun.reflect.Reflection");
- getCallerClass = sunReflectionClass.getDeclaredMethod("getCallerClass", int.class);
- Object o = getCallerClass.invoke(null, 0);
- getCallerClass.invoke(null, 0);
+ getCallerClassMethod = sunReflectionClass.getDeclaredMethod("getCallerClass", int.class);
+ Object o = getCallerClassMethod.invoke(null, 0);
+ getCallerClassMethod.invoke(null, 0);
if (o == null || o != sunReflectionClass) {
- getCallerClass = null;
+ getCallerClassMethod = null;
java7u25CompensationOffset = -1;
} else {
- o = getCallerClass.invoke(null, 1);
+ o = getCallerClassMethod.invoke(null, 1);
if (o == sunReflectionClass) {
- System.out.println("WARNING: Java 1.7.0_25 is in use which has a broken implementation of Reflection.getCallerClass(). " +
- " Please consider upgrading to Java 1.7.0_40 or later.");
+ System.out.println("WARNING: Unexpected result from sun.reflect.Reflection.getCallerClass(int), adjusting offset for future calls.");
java7u25CompensationOffset = 1;
}
}
} catch (final Exception | LinkageError e) {
System.out.println("WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.");
- getCallerClass = null;
+ getCallerClassMethod = null;
java7u25CompensationOffset = -1;
}
- GET_CALLER_CLASS = getCallerClass;
- JDK_7u25_OFFSET = java7u25CompensationOffset;
-
+ GET_CALLER_CLASS_METHOD = getCallerClassMethod;
+ JDK_7U25_OFFSET = java7u25CompensationOffset;
INSTANCE = new StackLocator();
}
+ /**
+ * Gets the singleton instance.
+ *
+ * @return the singleton instance.
+ */
public static StackLocator getInstance() {
return INSTANCE;
}
@@ -114,26 +118,41 @@ public final class StackLocator {
return clazz;
}
}
- return null;
+ return DEFAULT_CALLER_CLASS;
}
+ /**
+ * Gets the Class of the method that called <em>this</em> method at the location up the call stack by the given stack
+ * frame depth.
+ * <p>
+ * This method returns {@code null} if:
+ * </p>
+ * <ul>
+ * <li>{@code sun.reflect.Reflection.getCallerClass(int)} is not present.</li>
+ * <li>An exception is caught calling {@code sun.reflect.Reflection.getCallerClass(int)}.</li>
+ * </ul>
+ *
+ * @param depth The stack frame count to walk.
+ * @return A class or null.
+ * @throws IndexOutOfBoundsException if depth is negative.
+ */
// migrated from ReflectiveCallerClassUtility
@PerformanceSensitive
public Class<?> getCallerClass(final int depth) {
if (depth < 0) {
throw new IndexOutOfBoundsException(Integer.toString(depth));
}
- if (GET_CALLER_CLASS == null) {
- return null;
+ if (GET_CALLER_CLASS_METHOD == null) {
+ return DEFAULT_CALLER_CLASS;
}
// note that we need to add 1 to the depth value to compensate for this method, but not for the Method.invoke
// since Reflection.getCallerClass ignores the call to Method.invoke()
try {
- return (Class<?>) GET_CALLER_CLASS.invoke(null, depth + 1 + JDK_7u25_OFFSET);
+ return (Class<?>) GET_CALLER_CLASS_METHOD.invoke(null, depth + 1 + JDK_7U25_OFFSET);
} catch (final Exception e) {
// theoretically this could happen if the caller class were native code
// TODO: return Object.class
- return null;
+ return DEFAULT_CALLER_CLASS;
}
}
@@ -152,7 +171,7 @@ public final class StackLocator {
}
}
// TODO: return Object.class
- return null;
+ return DEFAULT_CALLER_CLASS;
}
// added for use in LoggerAdapter implementations mainly
@@ -198,7 +217,6 @@ public final class StackLocator {
for (int i = 0; i < stackTrace.length; i++) {
final String className = stackTrace[i].getClassName();
if (fqcnOfLogger.equals(className)) {
-
found = true;
continue;
}
@@ -212,9 +230,8 @@ public final class StackLocator {
public StackTraceElement getStackTraceElement(final int depth) {
// (MS) I tested the difference between using Throwable.getStackTrace() and Thread.getStackTrace(), and
// the version using Throwable was surprisingly faster! at least on Java 1.8. See ReflectionBenchmark.
- final StackTraceElement[] elements = new Throwable().getStackTrace();
int i = 0;
- for (final StackTraceElement element : elements) {
+ for (final StackTraceElement element : new Throwable().getStackTrace()) {
if (isValid(element)) {
if (i == depth) {
return element;
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocatorUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocatorUtil.java
index 72f181d..6f8a388 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocatorUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocatorUtil.java
@@ -71,6 +71,28 @@ public final class StackLocatorUtil {
}
/**
+ * Gets the ClassLoader of the class that called <em>this</em> method at the location up the call stack by the given
+ * stack frame depth.
+ * <p>
+ * This method returns {@code null} if:
+ * </p>
+ * <ul>
+ * <li>{@code sun.reflect.Reflection.getCallerClass(int)} is not present.</li>
+ * <li>An exception is caught calling {@code sun.reflect.Reflection.getCallerClass(int)}.</li>
+ * <li>Some Class implementations may use null to represent the bootstrap class loader.</li>
+ * </ul>
+ *
+ * @param depth The stack frame count to walk.
+ * @return A class or null.
+ * @throws IndexOutOfBoundsException if depth is negative.
+ */
+ @PerformanceSensitive
+ public static ClassLoader getCallerClassLoader(final int depth) {
+ final Class<?> callerClass = stackLocator.getCallerClass(depth + 1);
+ return callerClass != null ? callerClass.getClassLoader() : null;
+ }
+
+ /**
* Search for a calling class.
*
* @param sentinelClass Sentinel class at which to begin searching