mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-21 07:45:11 +00:00
6511515: poor performance of LogRecord.inferCaller depending on java.lang.Throwable.getStackTraceElement
Allow random access to stack trace elements; retrieve only needed ones Reviewed-by: swamyv
This commit is contained in:
parent
a5e977cf14
commit
5bf951e2a6
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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 <tt>index < 0 ||
|
||||
* index >= getStackTraceDepth() </tt>
|
||||
*/
|
||||
private native StackTraceElement getStackTraceElement(int index);
|
||||
native StackTraceElement getStackTraceElement(int index);
|
||||
|
||||
private synchronized void writeObject(java.io.ObjectOutputStream s)
|
||||
throws IOException
|
||||
|
||||
@ -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;
|
||||
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++;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
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.
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user