diff --git a/src/share/classes/java/lang/System.java b/src/share/classes/java/lang/System.java index 902591332def6b9433c0025fb3a2dfa7c073c1e4..00478bc9e1bb1884e525a445a617eb7fb96df739 100644 --- a/src/share/classes/java/lang/System.java +++ b/src/share/classes/java/lang/System.java @@ -1174,6 +1174,12 @@ public final class System { public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) { Shutdown.add(slot, registerShutdownInProgress, hook); } + public int getStackTraceDepth(Throwable t) { + return t.getStackTraceDepth(); + } + public StackTraceElement getStackTraceElement(Throwable t, int i) { + return t.getStackTraceElement(i); + } }); } diff --git a/src/share/classes/java/lang/Throwable.java b/src/share/classes/java/lang/Throwable.java index eb31505d15c25f9c9d05b2569d7ee24b7bbfa57b..c4e75d250ff9914b0095f0ebc7d4264d05743ae9 100644 --- a/src/share/classes/java/lang/Throwable.java +++ b/src/share/classes/java/lang/Throwable.java @@ -645,17 +645,21 @@ public class Throwable implements Serializable { /** * Returns the number of elements in the stack trace (or 0 if the stack * trace is unavailable). + * + * package-protection for use by SharedSecrets. */ - private native int getStackTraceDepth(); + native int getStackTraceDepth(); /** * Returns the specified element of the stack trace. * + * package-protection for use by SharedSecrets. + * * @param index index of the element to return. * @throws IndexOutOfBoundsException if index < 0 || * index >= getStackTraceDepth() */ - private native StackTraceElement getStackTraceElement(int index); + native StackTraceElement getStackTraceElement(int index); private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException diff --git a/src/share/classes/java/util/logging/LogRecord.java b/src/share/classes/java/util/logging/LogRecord.java index 0acf9fa78cde225d2b36b3c77c08f7d2b47e215f..2610316a5e38b7e1a08d2d5c11dd90f7c63d84b7 100644 --- a/src/share/classes/java/util/logging/LogRecord.java +++ b/src/share/classes/java/util/logging/LogRecord.java @@ -29,6 +29,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.io.*; +import sun.misc.JavaLangAccess; +import sun.misc.SharedSecrets; + /** * LogRecord objects are used to pass logging requests between * the logging framework and individual log Handlers. @@ -522,29 +525,31 @@ public class LogRecord implements java.io.Serializable { // Private method to infer the caller's class and method names private void inferCaller() { needToInferCaller = false; - // Get the stack trace. - StackTraceElement stack[] = (new Throwable()).getStackTrace(); - // First, search back to a method in the Logger class. - int ix = 0; - while (ix < stack.length) { - StackTraceElement frame = stack[ix]; + JavaLangAccess access = SharedSecrets.getJavaLangAccess(); + Throwable throwable = new Throwable(); + int depth = access.getStackTraceDepth(throwable); + + String logClassName = "java.util.logging.Logger"; + 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 (cname.equals("java.util.logging.Logger")) { - break; - } - ix++; - } - // Now search for the first frame before the "Logger" class. - while (ix < stack.length) { - StackTraceElement frame = stack[ix]; - String cname = frame.getClassName(); - if (!cname.equals("java.util.logging.Logger")) { - // We've found the relevant frame. - setSourceClassName(cname); - setSourceMethodName(frame.getMethodName()); - return; + if (lookingForLogger) { + // Skip all frames until we have found the first logger frame. + if (cname.equals(logClassName)) { + lookingForLogger = false; + } + } else { + if (!cname.equals(logClassName)) { + // We've found the relevant frame. + setSourceClassName(cname); + setSourceMethodName(frame.getMethodName()); + return; + } } - ix++; } // We haven't found a suitable frame, so just punt. This is // OK as we are only committed to making a "best effort" here. diff --git a/src/share/classes/sun/misc/JavaLangAccess.java b/src/share/classes/sun/misc/JavaLangAccess.java index 846a671b78dfecb50e1b6fd3036e87b4912d80e9..658b479be92c34633f44a9138472a5ebc9c1b048 100644 --- a/src/share/classes/sun/misc/JavaLangAccess.java +++ b/src/share/classes/sun/misc/JavaLangAccess.java @@ -73,4 +73,14 @@ public interface JavaLangAccess { * the slot is not valid to register. */ void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook); + + /** + * Returns the number of stack frames represented by the given throwable. + */ + int getStackTraceDepth(Throwable t); + + /** + * Returns the ith StackTraceElement for the given throwable. + */ + StackTraceElement getStackTraceElement(Throwable t, int i); }