Proposed API for JEP 259: Stack-Walking API
Remi Forax
forax at univ-mlv.fr
Wed Nov 18 11:22:40 UTC 2015
----- Mail original -----
> De: "David Holmes" <david.holmes at oracle.com>
> À: "Mandy Chung" <mandy.chung at oracle.com>, "Peter Levart" <peter.levart at gmail.com>
> Cc: "OpenJDK Dev list" <core-libs-dev at openjdk.java.net>
> Envoyé: Mercredi 18 Novembre 2015 08:58:56
> Objet: Re: Proposed API for JEP 259: Stack-Walking API
>
> On 18/11/2015 8:42 AM, Mandy Chung wrote:
> >
> >> On Nov 17, 2015, at 2:09 PM, Peter Levart <peter.levart at gmail.com> wrote:
> >>
> >> I think that calling getCallerClass() from implementation of Runnable::run
> >> should expect it to return a system class. It may be Thread.class or
> >> ThreadPoolExecutor$Worker.class or anything actually.
> >>
> >
> > I’m now convinced that it’s not a good idea to special case it.
> > getCallerClass will simply return the caller frame (i.e. top-2) on the
> > stack and throw UOE if there is no caller frame. The user should call
> > StackWalker::walk instead if this special case matters.
>
> That sounds good to me too.
>
> David
Looks good to me too if IllegalStateException is used instead of UnsupportedOperationException.
UnsuppportedOperationException is used when the operation is not available, here, the same code can work or not depending how it is called.
Runnable r = () -> System.out.println(stackWalker.getCallerClass());
new Thread(r).start() // throw ISE
r.run(); // prints main class
Rémi
>
> > How does this look?
> >
> > /**
> > * Gets the {@code Class} object of the caller invoking the method
> > * that calls this {@code getCallerClass} method.
> > *
> > * <p> Reflection frames, {@link java.lang.invoke.MethodHandle} and
> > * hidden frames are filtered regardless of the
> > * {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES}
> > * and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options
> > * if this {@code StackWalker} has been configured.
> > *
> > * <p> This method throws {@code UnsupportedOperationException} if
> > * this {@code StackWalker} is not configured with
> > * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option
> > * or this method is called from the last frame on the stack,
> > * i.e. invoked from a JNI attached thread (
> > * for example, {@code static public void main} method launched by the
> > * {@code java} launcher).
> > *
> > * @apiNote
> > * For example, {@code Util::getResourceBundle} loads a resource bundle
> > * on behalf of the caller. It calls this {@code getCallerClass} method
> > * to find the method calling {@code Util::getResourceBundle} and use the
> > caller's
> > * class loader to load the resource bundle. The caller class in this
> > example
> > * is the {@code MyTool} class.
> > *
> > * <pre>{@code
> > * class Util {
> > * private final StackWalker walker =
> > StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
> > * public ResourceBundle getResourceBundle(String bundleName) {
> > * Class<?> caller = walker.getCallerClass();
> > * return ResourceBundle.getBundle(bundleName,
> > caller.getClassLoader());
> > * }
> > * }
> > *
> > * class MyTool {
> > * private void init() {
> > * ResourceBundle rb = Util.getResourceBundle("mybundle");
> > * }
> > * }
> > * }</pre>
> > *
> > * An equivalent way to find the caller class using the
> > * {@link StackWalker#walk walk} method is as follows
> > * (filtering the reflection frames, {@code MethodHandle} and hidden
> > frames
> > * not shown below):
> > * <pre>{@code
> > * Optional<Class<?>> caller = walker.walk(s ->
> > * s.map(StackFrame::getDeclaringClass)
> > * .skip(2)
> > * .findFirst());
> > * }</pre>
> > *
> > * When the {@code getCallerClass} method is called from a method that
> > * is the last frame on the stack, i.e. invoked from a JNI attached
> > thread,
> > * for example, {@code static public void main} method launched by the
> > * {@code java} launcher,
> > *
> > * @return {@code Class} object of the caller's caller invoking this
> > method.
> > *
> > * @throws UnsupportedOperationException if this {@code StackWalker}
> > * is not configured with {@link Option#RETAIN_CLASS_REFERENCE
> > * Option.RETAIN_CLASS_REFERENCE}.
> > * @throws UnsupportedOperationException if there is no caller frame, i.e.
> > * when this {@code getCallerClass} method is called from a method
> > * which is the last frame on the stack.
> > */
> >
> > Mandy
> >
>
More information about the core-libs-dev
mailing list