提交 c5dde42c 编写于 作者: M martin

6511515: poor performance of LogRecord.inferCaller depending on...

6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
Summary: Allow random access to stack trace elements; retrieve only needed ones
Reviewed-by: swamyv
Contributed-by: jeremymanson@google.com
上级 d120bfcc
...@@ -1174,6 +1174,12 @@ public final class System { ...@@ -1174,6 +1174,12 @@ public final class System {
public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) { public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
Shutdown.add(slot, registerShutdownInProgress, 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);
}
}); });
} }
......
...@@ -645,17 +645,21 @@ public class Throwable implements Serializable { ...@@ -645,17 +645,21 @@ public class Throwable implements Serializable {
/** /**
* Returns the number of elements in the stack trace (or 0 if the stack * Returns the number of elements in the stack trace (or 0 if the stack
* trace is unavailable). * trace is unavailable).
*
* package-protection for use by SharedSecrets.
*/ */
private native int getStackTraceDepth(); native int getStackTraceDepth();
/** /**
* Returns the specified element of the stack trace. * Returns the specified element of the stack trace.
* *
* package-protection for use by SharedSecrets.
*
* @param index index of the element to return. * @param index index of the element to return.
* @throws IndexOutOfBoundsException if <tt>index &lt; 0 || * @throws IndexOutOfBoundsException if <tt>index &lt; 0 ||
* index &gt;= getStackTraceDepth() </tt> * index &gt;= getStackTraceDepth() </tt>
*/ */
private native StackTraceElement getStackTraceElement(int index); native StackTraceElement getStackTraceElement(int index);
private synchronized void writeObject(java.io.ObjectOutputStream s) private synchronized void writeObject(java.io.ObjectOutputStream s)
throws IOException throws IOException
......
...@@ -29,6 +29,9 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -29,6 +29,9 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.io.*; import java.io.*;
import sun.misc.JavaLangAccess;
import sun.misc.SharedSecrets;
/** /**
* LogRecord objects are used to pass logging requests between * LogRecord objects are used to pass logging requests between
* the logging framework and individual log Handlers. * the logging framework and individual log Handlers.
...@@ -522,29 +525,31 @@ public class LogRecord implements java.io.Serializable { ...@@ -522,29 +525,31 @@ public class LogRecord implements java.io.Serializable {
// Private method to infer the caller's class and method names // Private method to infer the caller's class and method names
private void inferCaller() { private void inferCaller() {
needToInferCaller = false; needToInferCaller = false;
// Get the stack trace. JavaLangAccess access = SharedSecrets.getJavaLangAccess();
StackTraceElement stack[] = (new Throwable()).getStackTrace(); Throwable throwable = new Throwable();
// First, search back to a method in the Logger class. int depth = access.getStackTraceDepth(throwable);
int ix = 0;
while (ix < stack.length) { String logClassName = "java.util.logging.Logger";
StackTraceElement frame = stack[ix]; 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(); String cname = frame.getClassName();
if (cname.equals("java.util.logging.Logger")) { if (lookingForLogger) {
break; // Skip all frames until we have found the first logger frame.
} if (cname.equals(logClassName)) {
ix++; lookingForLogger = false;
} }
// Now search for the first frame before the "Logger" class. } else {
while (ix < stack.length) { if (!cname.equals(logClassName)) {
StackTraceElement frame = stack[ix]; // We've found the relevant frame.
String cname = frame.getClassName(); setSourceClassName(cname);
if (!cname.equals("java.util.logging.Logger")) { setSourceMethodName(frame.getMethodName());
// We've found the relevant frame. return;
setSourceClassName(cname); }
setSourceMethodName(frame.getMethodName());
return;
} }
ix++;
} }
// We haven't found a suitable frame, so just punt. This is // We haven't found a suitable frame, so just punt. This is
// OK as we are only committed to making a "best effort" here. // OK as we are only committed to making a "best effort" here.
......
...@@ -73,4 +73,14 @@ public interface JavaLangAccess { ...@@ -73,4 +73,14 @@ public interface JavaLangAccess {
* the slot is not valid to register. * the slot is not valid to register.
*/ */
void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook); 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);
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册