JDK-6349551 : expose Throwable.getStackTraceElement(int)
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-11-14
  • Updated: 2017-07-20
  • Resolved: 2017-07-20
Related Reports
Relates :  
Description
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.

Comments
Request fulfilled by StackWalker, new in Java 9.
20-07-2017

EVALUATION This request was discussed with the author of private getStackTraceElement(int) method and the simple answer is that no usefulness for this method was anticipated. Making the method public may not be possible for various reasons. If this method must be left private then a functional equivalent method should be possible.
16-01-2006

EVALUATION (this CR accidently closed by mistake, reopened)
15-12-2005

EVALUATION Marking this incomplete specifically to stimulate discussion. These questions are meant to get to the heart of the requirements and implications: no intimidation is intended! General questions: 1) Is it really a big problem to capture all the elements and return a clone of a single one with a user-defined method? 2) How many cases of (1) would there be, really? Is this convenience for a miniscule user group? 3) How would a user of the proposed method decide which index value to provide, in terms of the parameter choice being the "right one", for example for log capture? 4) Would it really be sufficient to say "you'll know when you've run off the end because null will be returned"? Questions 3 and 4 are meant to wonder if it may frequently be the case that all the elements must be retrieved anyway! Other questions to explore: 1) Why wasn't this method public in the first place? 2) What are the implications of exposing it? This might very well be a candidate "Peabody project" if an acceptable API can be found and there is real usefulness involved. This isn't the only request for enhancement in this part of Java, either. (Finally, one quick observation of the proposed alternative method is that it returns a clone: is not mentioned but may be significant.)
14-11-2005