< prev index next >
jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java
Print this page
@@ -30,19 +30,17 @@
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.time.Clock;
-import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-import jdk.internal.misc.JavaLangAccess;
-import jdk.internal.misc.SharedSecrets;
+import java.util.Optional;
+import java.util.function.Predicate;
/**
* Platform logger provides an API for the JRE components to log
* messages. This enables the runtime components to eliminate the
* static dependency of the logging facility and also defers the
@@ -537,48 +535,60 @@
level.name(),
msg,
throwable);
}
- // Returns the caller's class and method's name; best effort
- // if cannot infer, return the logger's name.
- private String getCallerInfo() {
- String sourceClassName = null;
- String sourceMethodName = null;
+ /*
+ * CallerFinder is a stateful predicate.
+ */
+ static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
+ static final StackWalker WALKER = StackWalker.getInstance();
- JavaLangAccess access = SharedSecrets.getJavaLangAccess();
- Throwable throwable = new Throwable();
- int depth = access.getStackTraceDepth(throwable);
-
- String logClassName = "sun.util.logging.PlatformLogger";
- boolean lookingForLogger = true;
- for (int ix = 0; ix < depth; ix++) {
- // Calling getStackTraceElement directly prevents the VM
- // from paying the cost of building the entire stack frame.
- StackTraceElement frame =
- access.getStackTraceElement(throwable, ix);
- String cname = frame.getClassName();
- if (lookingForLogger) {
- // Skip all frames until we have found the first logger frame.
- if (cname.equals(logClassName)) {
- lookingForLogger = false;
+ /**
+ * Returns StackTraceElement of the caller's frame.
+ * @return StackTraceElement of the caller's frame.
+ */
+ Optional<StackWalker.StackFrame> get() {
+ return WALKER.walk(s -> s.filter(this).findFirst());
}
- } else {
- if (!cname.equals(logClassName)) {
- // We've found the relevant frame.
- sourceClassName = cname;
- sourceMethodName = frame.getMethodName();
- break;
+
+ private boolean lookingForLogger = true;
+
+ /**
+ * Returns true if we have found the caller's frame, false if the frame
+ * must be skipped.
+ *
+ * @param t The frame info.
+ * @return true if we have found the caller's frame, false if the frame
+ * must be skipped.
+ */
+ @Override
+ public boolean test(StackWalker.StackFrame t) {
+ final String cname = t.getClassName();
+ // We should skip all frames until we have found the logger,
+ // because these frames could be frames introduced by e.g. custom
+ // sub classes of Handler.
+ if (lookingForLogger) {
+ lookingForLogger = !cname.equals("sun.util.logging.PlatformLogger");
+ return false;
}
+ // Once the logger is found - we should skip all frames that
+ // point to packages which contain artifacts that could be
+ // inserted between the logger and its caller. These could be
+ // logger wrappers from j.u.l or sun.util.logging (e.g. the
+ // PlatformLogger or artifacts between the PlatformLogger and
+ // the actual logger) or frames inserted by use of reflection
+ // and/or doPrivileged calls.
+ return !cname.startsWith("java.util.logging.")
+ && !cname.startsWith("sun.util.logging.")
+ && !cname.startsWith("java.security.AccessController");
}
}
- if (sourceClassName != null) {
- return sourceClassName + " " + sourceMethodName;
- } else {
- return name;
- }
+ private String getCallerInfo() {
+ Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
+ return frame.map(f -> f.getClassName() + " " + f.getMethodName()).orElse(name);
}
}
/**
* JavaLoggerProxy forwards all the calls to its corresponding
< prev index next >