I also think IllegalStateException is better than UOE for this case as 
getCallerClass is inappropriate to be called where there is no caller frame.

Mandy

> On Nov 18, 2015, at 5:12 AM, fo...@univ-mlv.fr wrote:
> 
> Hi peter,
> Given this is a stack walker, considering the stack as a state seems natural 
> to me.
> 
> Rémi
> 
> ----- Mail original -----
>> De: "Peter Levart" <peter.lev...@gmail.com>
>> À: "Remi Forax" <fo...@univ-mlv.fr>, "David Holmes" <david.hol...@oracle.com>
>> Cc: "Mandy Chung" <mandy.ch...@oracle.com>, "OpenJDK Dev list" 
>> <core-libs-dev@openjdk.java.net>
>> Envoyé: Mercredi 18 Novembre 2015 13:26:32
>> Objet: Re: Proposed API for JEP 259: Stack-Walking API
>> 
>> 
>> 
>> On 11/18/2015 12:22 PM, Remi Forax wrote:
>>> ----- Mail original -----
>>>> De: "David Holmes" <david.hol...@oracle.com>
>>>> À: "Mandy Chung" <mandy.ch...@oracle.com>, "Peter Levart"
>>>> <peter.lev...@gmail.com>
>>>> Cc: "OpenJDK Dev list" <core-libs-dev@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.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
>>> 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.
>> 
>> But IllegalStateException is dependent on some state. There's no state
>> involved here (in the sense "state" is characterized in Java). My 1st
>> thought was an IllegalArgumentException. This requires some imagination
>> to view the caller passed to the method as an implicit argument.
>> 
>> There's an obscure java.util.EmptyStackException but that is reserved
>> for java.util.Stack operations.
>> 
>> If we consider the call stack to be part of the Thread state, then maybe
>> java.lang.IllegalThreadStateException (a subclass of
>> IllegalArgumentException) could be used...
>> 
>> Regards, Peter
>> 
>>> 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
>>>>> 
>> 
>> 

Reply via email to