On 18/11/2015 8:42 AM, Mandy Chung wrote:

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.

That sounds good to me too.

David

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

Reply via email to