--- old/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java 2015-11-09 17:14:56.000000000 -0800 +++ new/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java 2015-11-09 17:14:56.000000000 -0800 @@ -30,9 +30,9 @@ import java.util.concurrent.atomic.AtomicLong; import java.io.*; import java.time.Clock; - -import jdk.internal.misc.JavaLangAccess; -import jdk.internal.misc.SharedSecrets; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.function.Predicate; /** * LogRecord objects are used to pass logging requests between @@ -639,43 +639,62 @@ // Private method to infer the caller's class and method names private void inferCaller() { needToInferCaller = false; - JavaLangAccess access = SharedSecrets.getJavaLangAccess(); - Throwable throwable = new Throwable(); - int depth = access.getStackTraceDepth(throwable); - - 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(); - boolean isLoggerImpl = isLoggerImplFrame(cname); - if (lookingForLogger) { - // Skip all frames until we have found the first logger frame. - if (isLoggerImpl) { - lookingForLogger = false; - } - } else { - if (!isLoggerImpl) { - // skip reflection call - if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) { - // We've found the relevant frame. - setSourceClassName(cname); - setSourceMethodName(frame.getMethodName()); - return; - } - } - } - } + // Skip all frames until we have found the first logger frame. + Optional frame = new CallerFinder().get(); + frame.ifPresent(f -> { + setSourceClassName(f.getClassName()); + setSourceMethodName(f.getMethodName()); + }); + // We haven't found a suitable frame, so just punt. This is // OK as we are only committed to making a "best effort" here. } - private boolean isLoggerImplFrame(String cname) { - // the log record could be created for a platform logger - return (cname.equals("java.util.logging.Logger") || - cname.startsWith("java.util.logging.LoggingProxyImpl") || - cname.startsWith("sun.util.logging.")); + /* + * CallerFinder is a stateful predicate. + */ + static final class CallerFinder implements Predicate { + static final StackWalker WALKER = StackWalker.create(); + + /** + * Returns StackTraceElement of the caller's frame. + * @return StackTraceElement of the caller's frame. + */ + Optional get() { + return WALKER.walk((s) -> s.filter(this).findFirst()); + } + + 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("java.util.logging.Logger") && + !cname.startsWith("java.util.logging.LoggingProxyImpl") && + !cname.startsWith("sun.util.logging."); + 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.uti.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"); + } } }