On 09/20/2013 09:28 AM, Nick Williams wrote:
On Sep 20, 2013, at 2:09 AM, Mandy Chung wrote:
On 9/18/2013 9:22 AM, Nick Williams wrote:
Okay. Again, sorry for my absence. This wraps up my feedback for now. I now
await responses from Mandy.
On Sep 17, 2013, at 3:53 PM, Mandy Chung wrote:
You asked at a good time. I discussed this with John Rose last couple days on
this topic. He has been thinking about how to do fillInStackTrace performantly
and walk the stack with laziness and frame filtering. The current
implementation fills the entire stack trace while Groovy and Log4j use case
filters the frames of some specific classes until it reaches the first one not
being filtered.
He suggests to consider an API taking a callback shape (e.g. Function,
Consumer, etc) that Remi Forax suggested at one time that allows the JVM to do
something. I will work with John to work out the details and determine the
interface between VM and library and hash out issues.
I like the callback shape idea and hope to work out a proposal soon.
This will give you an idea the API we are thinking about:
http://cr.openjdk.java.net/~mchung/jdk8/webrevs/walkstack-webrev/
Just to be clear, this means the patch I worked on for a month has been
completely junked. Correct? Awesome.
More work to do as we are working on the VM interface and implementation.
We'll post an update when it's ready.
Stack is a "stream" that allows you to walk partial stack (e.g. find caller) or
full stack trace (e.g. throwable). The filtering and mapping operations are lazy to avoid
having the VM eagerly copying the entire stack trace data even for the short reach case
(like Groovy and Log4j).
The API takes a predicate, consumer or function so that the caller will only
need to carry the data it needs. There is no method to return the stream of
stack frames; otherwise, the returned stack frame stream would be a snapshot
and require to do fillInStackTrace and get the entire stack trace. The API can
also take a depth limit to control the number of elements and can use it as
optimization (currently the VM has a predefined max number of stack frames
returned in a stack trace).
This is all well and good, but some of us just need a simple array. This seems
like over-engineering. I just want an array of StackFrameInfos/StackTraceFrames.
I have modified java.util.logging.LogRecord to infer the caller using the new
API (much simpler):
StackTraceElement frame =
Thread.firstCaller(e -> {return !isLoggerImplFrame(e.getClassName()); },
StackFrameInfo::stackTraceElement);
Replacement for getCallerClass()
Class<?> c = Thread.getCaller(StackFrameInfo::getDeclaringClass);
Replacement for traversing the stack with getCallerClass(int depth)
Thread.walkStack(e -> doSomething(e));
This looks beautiful for Java 8, sure. Now try doing these same things in a
library compiled for Java 6 but made to be compatible with Java 8 and so all of
this has to happen via reflection. Suddenly it's nightmarish.
Hi,
Nick: You can always create a "facade" class that has a
reflection-friendly API and compile it with JDK8. You load this class
and use it via reflection if you detect JDK8 in runtime. It's just that
the build procedure is more complicated (you need both JDK6/7 and JDK8
compilers).
Mandy: I like the API. It covers the use-cases optimally. I can see how
StackStreamcould be implemented with a single JNI -> Java callback per
StackFrameInfo... Why not using the same call-back principle for
Throwable API too. Instead of implementing Throwable.walkStackTracein
terms of getStackTrace it could be the other way around. For
completeness, getCaller() and firstCaller() could also be added to
Throwable although we don't yet have a use-case for that.
Regards, Peter
Finally, none of the points I made and questions I raised a couple of days ago
have been addressed (see five emails on September 18). Particularly, the
security checks bother me and we _still_ have no explanation as to why they're
necessary.
Nick