< 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 >