A DESCRIPTION OF THE REQUEST :
There is no efficent way to access a single stack trace element.
Currently, the only public access to stack trace elements is via the getStackTrace() method in the java.lang.Throwable class. But it creates an array of ALL available stack trace elements (dozens or hundreds of objects). When only one element is needed, this is a lot of wasted CPU and memory.
The getStackTraceElement() method in that class performs exactly the desired function, but it is currently private scope.
JUSTIFICATION :
Logging frameworks (such as Log4J and the Java Logging API aka java.util.logging) must be as efficient as possible. Certain levels of logging can generate hundreds of log messages per second.
Developers rely on logged information to diagnose problems, both during development and after deployment. Logging frameworks offer ways to identify the source of log messages, such as the class name, method name, and even source code line number.
However, currently these most helpful items of data are discouraged in logging output because of the overhead involved - namely obtaining and accessing entire stack traces. In order to look up even one class name, current logging code is forced to use getStackTrace().
There are also occasions where it is useful to construct a Throwable object and look up specific stack trace information. Any method can find out who called it using this approach. There is no other way to accomplish this in Java.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Return just one StackTraceElement object, in as efficient a manner as possible, when only one is desired. Maximum run-time efficiency is the goal.
ACTUAL -
Many (dozens or even hundreds) of StackTraceElements are returned, even if only one is desired. This is exceedingly inefficient, especially in logging scenarios where it may occur hundreds of times per second (for example, during development with "trace" or "dump" logging levels enabled).
---------- BEGIN SOURCE ----------
The simplest solution is to change this line in java.lang.throwable:
private native StackTraceElement getStackTraceElement(int index);
to:
public native StackTraceElement getStackTraceElement(int index);
Another approach would be to add the following code to the java.lang.Throwable class:
/**
* Provides efficient access to a single stack trace element.
* This method is functionally equivalent to the following code:
* <blockquote><pre><code>
* StackTraceElement[] stackTrace = this.getStackTrace();
* return stackTrace[depth];
* </code></pre></blockquote>
* except that this method avoids the overhead of generating the
* entire stack trace when only one element is desired.
* This method method is particularly useful in logging code which
* looks up where this Throwable object was created and thrown in
* the source code.
*
* @param depth an index into the stack trace. Zero indicates the
* the top of the stack (the most recent method invocation in
* the sequence).
* @return the stack trace element pertaining to this throwable at the
* indicated depth. null is returned if the depth argument is
* negative or beyond the limit of available stack trace
* elements, or if no stack trace is available from the
* virtual machine.
* @see java.lang.Throwable#getStackTrace()
*/
public synchronized StackTraceElement
getStackTraceElementAtDepth(int depth) {
try {
return (StackTraceElement) getStackTraceElement(depth).clone();
} catch (IndexOutOfBoundsException ex) {
return null;
}
}
Of course, this approach is not as efficient as simply making the existing getStackTraceElement() method public. However, since getStackTraceElement() is also a native method, the desire to avoid direct access to that method may outweigh the performance benefit. Then again, the existing Throwable.fillInStackTrace() method is currently both native and public.
Part of my goal with this RFE is to have something to reference for further discussion. As a new jdk.contributor I'm more than willing to code this into Mustang. But I hope to kick the options around first in a forum or two.
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Edit Throwable.java as described above, and replace that class in the main Java lib/rt.jar file. Most companies (including mine) do NOT find this an acceptible solution.