< prev index next >

src/java.base/share/classes/java/lang/StackWalker.java

Print this page




 448      * which is the method calling this {@code forEach} method.
 449      *
 450      * <p> This method is equivalent to calling
 451      * <blockquote>
 452      * {@code walk(s -> { s.forEach(action); return null; });}
 453      * </blockquote>
 454      *
 455      * @param action an action to be performed on each {@code StackFrame}
 456      *               of the stack of the current thread
 457      */
 458     @CallerSensitive
 459     public void forEach(Consumer<? super StackFrame> action) {
 460         Objects.requireNonNull(action);
 461         StackStreamFactory.makeStackTraverser(this, s -> {
 462             s.forEach(action);
 463             return null;
 464         }).walk();
 465     }
 466 
 467     /**
 468      * Gets the {@code Class} object of the caller invoking the method
 469      * that calls this {@code getCallerClass} method.
 470      *
 471      * <p> Reflection frames, {@link java.lang.invoke.MethodHandle}, and
 472      * hidden frames are filtered regardless of the
 473      * {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES}
 474      * and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options
 475      * this {@code StackWalker} has been configured with.
 476      *




 477      * <p> This method throws {@code UnsupportedOperationException}
 478      * if this {@code StackWalker} is not configured with the
 479      * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option.
 480      * This method should be called when a caller frame is present.  If
 481      * it is called from the last frame on the stack,
 482      * {@code IllegalStateException} will be thrown.
 483      *
 484      * @apiNote
 485      * For example, {@code Util::getResourceBundle} loads a resource bundle
 486      * on behalf of the caller.  It calls this {@code getCallerClass} method
 487      * to find the method calling {@code Util::getResourceBundle} and uses the caller's
 488      * class loader to load the resource bundle. The caller class in this example
 489      * is the {@code MyTool} class.

 490      *
 491      * <pre>{@code
 492      * class Util {
 493      *     private final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
 494      *     public ResourceBundle getResourceBundle(String bundleName) {
 495      *         Class<?> caller = walker.getCallerClass();
 496      *         return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader());
 497      *     }
 498      * }
 499      *
 500      * class MyTool {
 501      *     private final Util util = new Util();
 502      *     private void init() {
 503      *         ResourceBundle rb = util.getResourceBundle("mybundle");
 504      *     }
 505      * }
 506      * }</pre>
 507      *
 508      * An equivalent way to find the caller class using the
 509      * {@link StackWalker#walk walk} method is as follows
 510      * (filtering the reflection frames, {@code MethodHandle} and hidden frames
 511      * not shown below):
 512      * <pre>{@code
 513      *     Optional<Class<?>> caller = walker.walk(s ->
 514      *         s.map(StackFrame::getDeclaringClass)
 515      *          .skip(2)
 516      *          .findFirst());
 517      * }</pre>
 518      *
 519      * When the {@code getCallerClass} method is called from a method that
 520      * is the last frame on the stack,
 521      * for example, {@code static public void main} method launched by the
 522      * {@code java} launcher, or a method invoked from a JNI attached thread,
 523      * {@code IllegalStateException} is thrown.
 524      *
 525      * @return {@code Class} object of the caller's caller invoking this method.
 526      *
 527      * @throws UnsupportedOperationException if this {@code StackWalker}
 528      *         is not configured with {@link Option#RETAIN_CLASS_REFERENCE
 529      *         Option.RETAIN_CLASS_REFERENCE}.
 530      * @throws IllegalStateException if there is no caller frame, i.e.
 531      *         when this {@code getCallerClass} method is called from a method
 532      *         which is the last frame on the stack.
 533      */
 534     @CallerSensitive
 535     public Class<?> getCallerClass() {
 536         if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) {
 537             throw new UnsupportedOperationException("This stack walker " +
 538                     "does not have RETAIN_CLASS_REFERENCE access");
 539         }
 540 
 541         return StackStreamFactory.makeCallerFinder(this).findCaller();
 542     }
 543 
 544     // ---- package access ----
 545 
 546     static StackWalker newInstance(Set<Option> options, ExtendedOption extendedOption) {
 547         EnumSet<Option> optionSet = toEnumSet(options);
 548         checkPermission(optionSet);
 549         return new StackWalker(optionSet, 0, extendedOption);
 550     }


 448      * which is the method calling this {@code forEach} method.
 449      *
 450      * <p> This method is equivalent to calling
 451      * <blockquote>
 452      * {@code walk(s -> { s.forEach(action); return null; });}
 453      * </blockquote>
 454      *
 455      * @param action an action to be performed on each {@code StackFrame}
 456      *               of the stack of the current thread
 457      */
 458     @CallerSensitive
 459     public void forEach(Consumer<? super StackFrame> action) {
 460         Objects.requireNonNull(action);
 461         StackStreamFactory.makeStackTraverser(this, s -> {
 462             s.forEach(action);
 463             return null;
 464         }).walk();
 465     }
 466 
 467     /**
 468      * Gets the {@code Class} object of the caller who invoked the method
 469      * that invoked {@code getCallerClass}.
 470      *
 471      * <p> Reflection frames, {@link java.lang.invoke.MethodHandle}, and
 472      * hidden frames are filtered regardless of the
 473      * {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES}
 474      * and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options
 475      * this {@code StackWalker} has been configured with.
 476      *
 477      * <p> This method should be called when a caller frame is present.  If
 478      * it is called from the bottom most frame on the stack,
 479      * {@code IllegalCallerException} will be thrown.
 480      *
 481      * <p> This method throws {@code UnsupportedOperationException}
 482      * if this {@code StackWalker} is not configured with the
 483      * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option.



 484      *
 485      * @apiNote
 486      * For example, {@code Util::getResourceBundle} loads a resource bundle
 487      * on behalf of the caller.  It invokes {@code getCallerClass} to identify
 488      * the class whose method called {@code Util::getResourceBundle}.
 489      * Then, it obtains the class loader of that class, and uses
 490      * the class loader to load the resource bundle. The caller class
 491      * in this example is {@code MyTool}.
 492      *
 493      * <pre>{@code
 494      * class Util {
 495      *     private final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
 496      *     public ResourceBundle getResourceBundle(String bundleName) {
 497      *         Class<?> caller = walker.getCallerClass();
 498      *         return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader());
 499      *     }
 500      * }
 501      *
 502      * class MyTool {
 503      *     private final Util util = new Util();
 504      *     private void init() {
 505      *         ResourceBundle rb = util.getResourceBundle("mybundle");
 506      *     }
 507      * }
 508      * }</pre>
 509      *
 510      * An equivalent way to find the caller class using the
 511      * {@link StackWalker#walk walk} method is as follows
 512      * (filtering the reflection frames, {@code MethodHandle} and hidden frames
 513      * not shown below):
 514      * <pre>{@code
 515      *     Optional<Class<?>> caller = walker.walk(s ->
 516      *         s.map(StackFrame::getDeclaringClass)
 517      *          .skip(2)
 518      *          .findFirst());
 519      * }</pre>
 520      *
 521      * When the {@code getCallerClass} method is called from a method that
 522      * is the bottom most frame on the stack,
 523      * for example, {@code static public void main} method launched by the
 524      * {@code java} launcher, or a method invoked from a JNI attached thread,
 525      * {@code IllegalCallerException} is thrown.
 526      *
 527      * @return {@code Class} object of the caller's caller invoking this method.
 528      *
 529      * @throws UnsupportedOperationException if this {@code StackWalker}
 530      *         is not configured with {@link Option#RETAIN_CLASS_REFERENCE
 531      *         Option.RETAIN_CLASS_REFERENCE}.
 532      * @throws IllegalCallerException if there is no caller frame, i.e.
 533      *         when this {@code getCallerClass} method is called from a method
 534      *         which is the last frame on the stack.
 535      */
 536     @CallerSensitive
 537     public Class<?> getCallerClass() {
 538         if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) {
 539             throw new UnsupportedOperationException("This stack walker " +
 540                     "does not have RETAIN_CLASS_REFERENCE access");
 541         }
 542 
 543         return StackStreamFactory.makeCallerFinder(this).findCaller();
 544     }
 545 
 546     // ---- package access ----
 547 
 548     static StackWalker newInstance(Set<Option> options, ExtendedOption extendedOption) {
 549         EnumSet<Option> optionSet = toEnumSet(options);
 550         checkPermission(optionSet);
 551         return new StackWalker(optionSet, 0, extendedOption);
 552     }
< prev index next >