Draft JEP: Efficient Stack Walking API (original) (raw)
Mandy Chung mandy.chung at oracle.com
Sun Mar 30 23:02:19 UTC 2014
- Previous message: Wrong encoding after XML identity transformation
- Next message: RFR: 8038307: JAX-WS conformance tests fail when running JCK-devtools-8 suite against RI in EBCDIC emulation mode
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Below is a draft JEP we are considering submitting for JDK 9.
Mandy
Title: Efficient API for Stack Walking
Goal
Define a standard API for stack walking that will be efficient and performant.
Non-goal
It is not a goal for this API be easy to use via Reflection for example use in code that is compiled for an older JDK.
Motivation
There is no standard API to obtain information about the caller's class
and traverse the execution stack in a performant way. Existing libraries
and frameworks such as Log4j and Groovy have to resort to using the
JDK internal API sun.reflect.Reflection.getCallerClass(int depth)
.
This JEP proposes to define a standard API for stack walking that will be efficient and performant and also enable the implementation up level the stack walk machinery from the VM to Java and replaces the current mechanism of `Throwable.fillInStackTrace.
Description
There is no standard API to traverse certain frames on the execution stack efficiently and access the Class instance of each frame.
There are APIs that allow to access the stack trace information:
Throwable.getStackTrace()
andThread.getStackTrace()
that returns an array ofStackTraceElement
which contains the classname and method name of a stack trace.SecurityManager.getClassContext()
which is a protected method such that onlySecurityManager
subclass can access the class context.
These APIs require the VM to eagerly capture a snapshot of the entire
stack trace and returns the information representing the entire stack.
There is no other way to avoid the cost to examine all frames if
the caller is only interested in the top few frames on the stack.
Both Throwable.getStackTrace()
and Thread.getStackTrace()
methods
return an array of StackTraceElement
that contains the classname and
method name of a stack frame but the Class
instance.
In fact, for applications interested in the entire stack, the specification
allows VM implementation to omit some frames in the stack for performance.
In other words, Thread.getStackTrace()
may return a partial stack trace.
These APIs do not satisfy the use cases that currently depend on
the getCallerClass(int depth)
method or its performance overhead
is intolerable. The use cases include:
JDK caller-sensitive APIs look up its immediate caller's class which will be used to determine the behavior of the API. For example
Class.forName(String classname)
andResourceBundle.getBundle(String rbname)
methods use the immediate caller's class loader to load a class and a resource bundle respectively.Class.getMethod
etc will use the immediate caller's class loader to determine the security checks to be performed.java.util.logging
, Log4j and Groovy runtime filter the intermediary stack frames (typically implementation-specific and reflection frames) and find the caller's class to be used by the runtime of such library or framework.Traverse the entire stack trace or the stack trace of a
Throwbale
and obtain additional information about classes for enhanced diagnosibility in addition to the class and method name.
This JEP will define a stack walk API that allows laziness, frame filtering, supports short reaches to stop at a frame matching some criteria as well as long reaches to traverse the entire stack trace. This would need the JVM to provide a flexible mechanism to traverse and materialize the specific stack frame information to be used and allow efficient lazy access to additional stack frames when required. Native JVM transitions should be minimzed.
The API will define how it works when running with a security manager
that allows access to a Class
instance
of any frame ensuring that the security is not compromised.
An example API to walk the stack can be like: Thread.walkStack(Consumer action, int depthLimit)
that takes a callback to be invoked for each frame traversed. A variant of the walkStack method will take a predicate for stack frame filtering.
Thread.getCaller(Function<StackFrameInfo, R> function)
Thread.findCaller(Predicate<StackFrameInfo> predicate,
Function<StackFrameInfo, R> function)
finds the caller frame with or without filtering.
Testing
Unit tests and JCK tests for the new SE API will need to be developed. In addition, the performance of the new API for different use cases will be assessed.
Impact
Performance/scalability: performance measurement shall be performed using micro-benchmarks as well as real world usage of
getCallerClass
replaced with the new API.TCK: New JCK test cases shall be developed.
- Previous message: Wrong encoding after XML identity transformation
- Next message: RFR: 8038307: JAX-WS conformance tests fail when running JCK-devtools-8 suite against RI in EBCDIC emulation mode
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]