Hi, I’m happy to hear that, I was just about to post more convoluted examples against special-casing (i.e.
new Thread(r).start(); vs. new Thread(r) {}.start(); vs. new Thread(new Thread(r)) {}.start(); vs. new Thread(new Thread(r) {}).start(); ). Apart from the orphaned paragraph fragment at the end looks good to me, but that’s just my opinion. Sent from Mail for Windows 10 From: Mandy Chung Sent: Tuesday, November 17, 2015 23:43 To: Peter Levart Cc: OpenJDK Dev list Subject: Re: Proposed API for JEP 259: Stack-Walking API > On Nov 17, 2015, at 2:09 PM, Peter Levart <peter.lev...@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. 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