1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.lang;
  26 
  27 import sun.reflect.CallerSensitive;
  28 
  29 import java.util.*;
  30 import java.util.function.Consumer;
  31 import java.util.function.Function;
  32 import java.util.stream.Stream;
  33 
  34 /**
  35  * A stack walker.
  36  *
  37  * <p> The {@link StackWalker#walk walk} method opens a sequential stream
  38  * of {@link StackFrame StackFrame}s for the current thread and then applies
  39  * the given function to walk the {@code StackFrame} stream.
  40  * The stream reports stack frame elements in order, from the top most frame
  41  * that represents the execution point at which the stack was generated to
  42  * the bottom most frame.
  43  * The {@code StackFrame} stream is closed when the {@code walk} method returns.
  44  * If an attempt is made to reuse the closed stream,
  45  * {@code IllegalStateException} will be thrown.
  46  *
  47  * <p> The {@linkplain Option <em>stack walking options</em>} of a
  48  * {@code StackWalker} determines the information of
  49  * {@link StackFrame StackFrame} objects to be returned.
  50  * By default, stack frames of the reflection API and implementation
  51  * classes are {@linkplain Option#SHOW_HIDDEN_FRAMES hidden}
  52  * and {@code StackFrame}s have the class name and method name
  53  * available but not the {@link StackFrame#getDeclaringClass() Class reference}.
  54  *
  55  * <p> {@code StackWalker} is thread-safe. Multiple threads can share
  56  * a single {@code StackWalker} object to traverse its own stack.
  57  * A permission check is performed when a {@code StackWalker} is created,
  58  * according to the options it requests.
  59  * No further permission check is done at stack walking time.
  60  *
  61  * @apiNote
  62  * Examples
  63  *
  64  * <p>1. To find the first caller filtering a known list of implementation class:
  65  * <pre>{@code
  66  *     StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
  67  *     Optional<Class<?>> callerClass = walker.walk(s ->
  68  *         s.map(StackFrame::getDeclaringClass)
  69  *          .filter(interestingClasses::contains)
  70  *          .findFirst());
  71  * }</pre>
  72  *
  73  * <p>2. To snapshot the top 10 stack frames of the current thread,
  74  * <pre>{@code
  75  *     List<StackFrame> stack = StackWalker.getInstance().walk(s ->
  76  *         s.limit(10).collect(Collectors.toList()));
  77  * }</pre>
  78  *
  79  * Unless otherwise noted, passing a {@code null} argument to a
  80  * constructor or method in this {@code StackWalker} class
  81  * will cause a {@link NullPointerException NullPointerException}
  82  * to be thrown.
  83  *
  84  * @since 9
  85  */
  86 public final class StackWalker {
  87     /**
  88      * A {@code StackFrame} object represents a method invocation returned by
  89      * {@link StackWalker}.
  90      *
  91      * <p> The {@link #getDeclaringClass()} method may be unsupported as determined
  92      * by the {@linkplain Option stack walking options} of a {@linkplain
  93      * StackWalker stack walker}.
  94      *
  95      * @since 9
  96      * @jvms 2.6
  97      */
  98     public static interface StackFrame {
  99         /**
 100          * Gets the <a href="ClassLoader.html#name">binary name</a>
 101          * of the declaring class of the method represented by this stack frame.
 102          *
 103          * @return the binary name of the declaring class of the method
 104          *         represented by this stack frame
 105          *
 106          * @jls 13.1 The Form of a Binary
 107          */
 108         public String getClassName();
 109 
 110         /**
 111          * Gets the name of the method represented by this stack frame.
 112          * @return the name of the method represented by this stack frame
 113          */
 114         public String getMethodName();
 115 
 116         /**
 117          * Gets the declaring {@code Class} for the method represented by
 118          * this stack frame.
 119          *
 120          * @return the declaring {@code Class} of the method represented by
 121          * this stack frame
 122          *
 123          * @throws UnsupportedOperationException if this {@code StackWalker}
 124          *         is not configured with {@link Option#RETAIN_CLASS_REFERENCE
 125          *         Option.RETAIN_CLASS_REFERENCE}.
 126          */
 127         public Class<?> getDeclaringClass();
 128 
 129         /**
 130          * Returns the name of the source file containing the execution point
 131          * represented by this stack frame.  Generally, this corresponds
 132          * to the {@code SourceFile} attribute of the relevant {@code class}
 133          * file as defined by <cite>The Java Virtual Machine Specification</cite>.
 134          * In some systems, the name may refer to some source code unit
 135          * other than a file, such as an entry in a source repository.
 136          *
 137          * @return the name of the file containing the execution point
 138          *         represented by this stack frame, or empty {@code Optional}
 139          *         is unavailable.
 140          *
 141          * @jvms 4.7.10 The {@code SourceFile} Attribute
 142          */
 143         public Optional<String> getFileName();
 144 
 145         /**
 146          * Returns the line number of the source line containing the execution
 147          * point represented by this stack frame.  Generally, this is
 148          * derived from the {@code LineNumberTable} attribute of the relevant
 149          * {@code class} file as defined by <cite>The Java Virtual Machine
 150          * Specification</cite>.
 151          *
 152          * @return the line number of the source line containing the execution
 153          *         point represented by this stack frame, or empty
 154          *         {@code Optional} if this information is unavailable.
 155          *
 156          * @jvms 4.7.12 The {@code LineNumberTable} Attribute
 157          */
 158         public OptionalInt getLineNumber();
 159 
 160         /**
 161          * Returns {@code true} if the method containing the execution point
 162          * represented by this stack frame is a native method.
 163          *
 164          * @return {@code true} if the method containing the execution point
 165          *         represented by this stack frame is a native method.
 166          */
 167         public boolean isNativeMethod();
 168 
 169         /**
 170          * Gets a {@code StackTraceElement} for this stack frame.
 171          *
 172          * @return {@code StackTraceElement} for this stack frame.
 173          *
 174          * */
 175         public default StackTraceElement toStackTraceElement() {
 176             int lineNumber = isNativeMethod() ? -2
 177                                               : getLineNumber().orElse(-1);
 178             return new StackTraceElement(getClassName(), getMethodName(),
 179                                          getFileName().orElse(null),
 180                                          lineNumber);
 181         }
 182     }
 183 
 184     /**
 185      * Stack walker option to configure the {@linkplain StackFrame stack frame}
 186      * information obtained by a {@code StackWalker}.
 187      *
 188      * @since 9
 189      */
 190     public enum Option {
 191         /**
 192          * Retains {@code Class} object in {@code StackFrame}s
 193          * walked by this {@code StackWalker}.
 194          *
 195          * <p> A {@code StackWalker} configured with this option will support
 196          * {@link StackWalker#getCallerClass()} and
 197          * {@link StackFrame#getDeclaringClass() StackFrame.getDeclaringClass()}.
 198          */
 199         RETAIN_CLASS_REFERENCE,
 200         /**
 201          * Shows all reflection frames.
 202          *
 203          * <p>By default, reflection frames are hidden.  This includes the
 204          * {@link java.lang.reflect.Method#invoke} method
 205          * and the reflection implementation classes. A {@code StackWalker} with
 206          * this {@code SHOW_REFLECT_FRAMES} option will show all reflection frames.
 207          * The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all
 208          * reflection frames and it will also show other hidden frames that
 209          * are implementation-specific.
 210          */
 211         SHOW_REFLECT_FRAMES,
 212         /**
 213          * Shows all hidden frames.
 214          *
 215          * <p>A Java Virtual Machine implementation may hide implementation
 216          * specific frames in addition to {@linkplain #SHOW_REFLECT_FRAMES
 217          * reflection frames}. A {@code StackWalker} with this {@code SHOW_HIDDEN_FRAMES}
 218          * option will show all hidden frames (including reflection frames).
 219          */
 220         SHOW_HIDDEN_FRAMES;
 221     }
 222 
 223     enum ExtendedOption {
 224         /**
 225          * Obtain monitors, locals and operands.
 226          */
 227         LOCALS_AND_OPERANDS
 228     };
 229 
 230     static final EnumSet<Option> DEFAULT_EMPTY_OPTION = EnumSet.noneOf(Option.class);
 231 
 232     private final static StackWalker DEFAULT_WALKER =
 233         new StackWalker(DEFAULT_EMPTY_OPTION);
 234 
 235     private final Set<Option> options;
 236     private final ExtendedOption extendedOption;
 237     private final int estimateDepth;
 238 
 239     /**
 240      * Returns a {@code StackWalker} instance.
 241      *
 242      * <p> This {@code StackWalker} is configured to skip all
 243      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
 244      * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 245      *
 246      * @return a {@code StackWalker} configured to skip all
 247      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
 248      * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 249      *
 250      */
 251     public static StackWalker getInstance() {
 252         // no permission check needed
 253         return DEFAULT_WALKER;
 254     }
 255 
 256     /**
 257      * Returns a {@code StackWalker} instance with the given option specifying
 258      * the stack frame information it can access.
 259      *
 260      * <p>
 261      * If a security manager is present and the given {@code option} is
 262      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 263      * it calls its {@link SecurityManager#checkPermission checkPermission}
 264      * method for {@code StackFramePermission("retainClassReference")}.
 265      *
 266      * @param option {@link Option stack walking option}
 267      *
 268      * @return a {@code StackWalker} configured with the given option
 269      *
 270      * @throws SecurityException if a security manager exists and its
 271      *         {@code checkPermission} method denies access.
 272      */
 273     public static StackWalker getInstance(Option option) {
 274         return getInstance(EnumSet.of(Objects.requireNonNull(option)));
 275     }
 276 
 277     /**
 278      * Returns a {@code StackWalker} instance with the given {@code options} specifying
 279      * the stack frame information it can access.  If the given {@code options}
 280      * is empty, this {@code StackWalker} is configured to skip all
 281      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
 282      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 283      *
 284      * <p>
 285      * If a security manager is present and the given {@code options} contains
 286      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 287      * it calls its {@link SecurityManager#checkPermission checkPermission}
 288      * method for {@code StackFramePermission("retainClassReference")}.
 289      *
 290      * @param options {@link Option stack walking option}
 291      *
 292      * @return a {@code StackWalker} configured with the given options
 293      *
 294      * @throws SecurityException if a security manager exists and its
 295      *         {@code checkPermission} method denies access.
 296      */
 297     public static StackWalker getInstance(Set<Option> options) {
 298         if (options.isEmpty()) {
 299             return DEFAULT_WALKER;
 300         }
 301 
 302         checkPermission(options);
 303         return new StackWalker(toEnumSet(options));
 304     }
 305 
 306     /**
 307      * Returns a {@code StackWalker} instance with the given {@code options} specifying
 308      * the stack frame information it can access. If the given {@code options}
 309      * is empty, this {@code StackWalker} is configured to skip all
 310      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
 311      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 312      *
 313      * <p>
 314      * If a security manager is present and the given {@code options} contains
 315      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 316      * it calls its {@link SecurityManager#checkPermission checkPermission}
 317      * method for {@code StackFramePermission("retainClassReference")}.
 318      *
 319      * <p>
 320      * The {@code estimateDepth} specifies the estimate number of stack frames
 321      * this {@code StackWalker} will traverse that the {@code StackWalker} could
 322      * use as a hint for the buffer size.
 323      *
 324      * @param options {@link Option stack walking options}
 325      * @param estimateDepth Estimate number of stack frames to be traversed.
 326      *
 327      * @return a {@code StackWalker} configured with the given options
 328      *
 329      * @throws IllegalArgumentException if {@code estimateDepth <= 0}
 330      * @throws SecurityException if a security manager exists and its
 331      *         {@code checkPermission} method denies access.
 332      */
 333     public static StackWalker getInstance(Set<Option> options, int estimateDepth) {
 334         if (estimateDepth <= 0) {
 335             throw new IllegalArgumentException("estimateDepth must be > 0");
 336         }
 337         checkPermission(options);
 338         return new StackWalker(toEnumSet(options), estimateDepth);
 339     }
 340 
 341     // ----- private constructors ------
 342     private StackWalker(EnumSet<Option> options) {
 343         this(options, 0, null);
 344     }
 345     private StackWalker(EnumSet<Option> options, int estimateDepth) {
 346         this(options, estimateDepth, null);
 347     }
 348     private StackWalker(EnumSet<Option> options, int estimateDepth, ExtendedOption extendedOption) {
 349         this.options = options;
 350         this.estimateDepth = estimateDepth;
 351         this.extendedOption = extendedOption;
 352     }
 353 
 354     private static void checkPermission(Set<Option> options) {
 355         Objects.requireNonNull(options);
 356         SecurityManager sm = System.getSecurityManager();
 357         if (sm != null) {
 358             if (options.contains(Option.RETAIN_CLASS_REFERENCE)) {
 359                 sm.checkPermission(new StackFramePermission("retainClassReference"));
 360             }
 361         }
 362     }
 363 
 364     /*
 365      * Returns a defensive copy
 366      */
 367     private static EnumSet<Option> toEnumSet(Set<Option> options) {
 368         Objects.requireNonNull(options);
 369         if (options.isEmpty()) {
 370             return DEFAULT_EMPTY_OPTION;
 371         } else {
 372             return EnumSet.copyOf(options);
 373         }
 374     }
 375 
 376     /**
 377      * Applies the given function to the stream of {@code StackFrame}s
 378      * for the current thread, traversing from the top frame of the stack,
 379      * which is the method calling this {@code walk} method.
 380      *
 381      * <p>The {@code StackFrame} stream will be closed when
 382      * this method returns.  When a closed {@code Stream<StackFrame>} object
 383      * is reused, {@code IllegalStateException} will be thrown.
 384      *
 385      * @apiNote
 386      * For example, to find the first 10 calling frames, first skipping those frames
 387      * whose declaring class is in package {@code com.foo}:
 388      * <blockquote>
 389      * <pre>{@code
 390      * List<StackFrame> frames = StackWalker.getInstance().walk(s ->
 391      *     s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
 392      *      .limit(10)
 393      *      .collect(Collectors.toList()));
 394      * }</pre></blockquote>
 395      *
 396      * <p>This method takes a {@code Function} accepting a {@code Stream<StackFrame>},
 397      * rather than returning a {@code Stream<StackFrame>} and allowing the
 398      * caller to directly manipulate the stream. The Java virtual machine is
 399      * free to reorganize a thread's control stack, for example, via
 400      * deoptimization. By taking a {@code Function} parameter, this method
 401      * allows access to stack frames through a stable view of a thread's control
 402      * stack.
 403      *
 404      * <p>Parallel execution is effectively disabled and stream pipeline
 405      * execution will only occur on the current thread.
 406      *
 407      * @implNote The implementation stabilizes the stack by anchoring a frame
 408      * specific to the stack walking and ensures that the stack walking is
 409      * performed above the anchored frame. When the stream object is closed or
 410      * being reused, {@code IllegalStateException} will be thrown.
 411      *
 412      * @param function a function that takes a stream of
 413      *                 {@linkplain StackFrame stack frames} and returns a result.
 414      * @param <T> The type of the result of applying the function to the
 415      *            stream of {@linkplain StackFrame stack frame}.
 416      *
 417      * @return the result of applying the function to the stream of
 418      *         {@linkplain StackFrame stack frame}.
 419      */
 420     @CallerSensitive
 421     public <T> T walk(Function<? super Stream<StackFrame>, ? extends T> function) {
 422         // Returning a Stream<StackFrame> would be unsafe, as the stream could
 423         // be used to access the stack frames in an uncontrolled manner.  For
 424         // example, a caller might pass a Spliterator of stack frames after one
 425         // or more frames had been traversed. There is no robust way to detect
 426         // whether the execution point when
 427         // Spliterator.tryAdvance(java.util.function.Consumer<? super T>) is
 428         // invoked is the exact same execution point where the stack frame
 429         // traversal is expected to resume.
 430 
 431         Objects.requireNonNull(function);
 432         return StackStreamFactory.makeStackTraverser(this, function)
 433                                  .walk();
 434     }
 435 
 436     /**
 437      * Performs the given action on each element of {@code StackFrame} stream
 438      * of the current thread, traversing from the top frame of the stack,
 439      * which is the method calling this {@code forEach} method.
 440      *
 441      * <p> This method is equivalent to calling
 442      * <blockquote>
 443      * {@code walk(s -> { s.forEach(action); return null; });}
 444      * </blockquote>
 445      *
 446      * @param action an action to be performed on each {@code StackFrame}
 447      *               of the stack of the current thread
 448      */
 449     @CallerSensitive
 450     public void forEach(Consumer<? super StackFrame> action) {
 451         Objects.requireNonNull(action);
 452         StackStreamFactory.makeStackTraverser(this, s -> {
 453             s.forEach(action);
 454             return null;
 455         }).walk();
 456     }
 457 
 458     /**
 459      * Gets the {@code Class} object of the caller invoking the method
 460      * that calls this {@code getCallerClass} method.
 461      *
 462      * <p> Reflection frames, {@link java.lang.invoke.MethodHandle} and
 463      * hidden frames are filtered regardless of the
 464      * {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES}
 465      * and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options
 466      * this {@code StackWalker} has been configured.
 467      *
 468      * <p> This method throws {@code UnsupportedOperationException}
 469      * if this {@code StackWalker} is not configured with
 470      * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option,
 471      * This method should be called when a caller frame is present.  If
 472      * it is called from the last frame on the stack;
 473      * {@code IllegalStateException} will be thrown.
 474      *
 475      * @apiNote
 476      * For example, {@code Util::getResourceBundle} loads a resource bundle
 477      * on behalf of the caller.  It calls this {@code getCallerClass} method
 478      * to find the method calling {@code Util::getResourceBundle} and use the caller's
 479      * class loader to load the resource bundle. The caller class in this example
 480      * is the {@code MyTool} class.
 481      *
 482      * <pre>{@code
 483      * class Util {
 484      *     private final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
 485      *     public ResourceBundle getResourceBundle(String bundleName) {
 486      *         Class<?> caller = walker.getCallerClass();
 487      *         return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader());
 488      *     }
 489      * }
 490      *
 491      * class MyTool {
 492      *     private final Util util = new Util();
 493      *     private void init() {
 494      *         ResourceBundle rb = util.getResourceBundle("mybundle");
 495      *     }
 496      * }
 497      * }</pre>
 498      *
 499      * An equivalent way to find the caller class using the
 500      * {@link StackWalker#walk walk} method is as follows
 501      * (filtering the reflection frames, {@code MethodHandle} and hidden frames
 502      * not shown below):
 503      * <pre>{@code
 504      *     Optional<Class<?>> caller = walker.walk(s ->
 505      *         s.map(StackFrame::getDeclaringClass)
 506      *          .skip(2)
 507      *          .findFirst());
 508      * }</pre>
 509      *
 510      * When the {@code getCallerClass} method is called from a method that
 511      * is the last frame on the stack,
 512      * for example, {@code static public void main} method launched by the
 513      * {@code java} launcher or a method invoked from a JNI attached thread.
 514      * {@code IllegalStateException} is thrown.
 515      *
 516      * @return {@code Class} object of the caller's caller invoking this method.
 517      *
 518      * @throws UnsupportedOperationException if this {@code StackWalker}
 519      *         is not configured with {@link Option#RETAIN_CLASS_REFERENCE
 520      *         Option.RETAIN_CLASS_REFERENCE}.
 521      * @throws IllegalStateException if there is no caller frame, i.e.
 522      *         when this {@code getCallerClass} method is called from a method
 523      *         which is the last frame on the stack.
 524      */
 525     @CallerSensitive
 526     public Class<?> getCallerClass() {
 527         if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) {
 528             throw new UnsupportedOperationException("This stack walker " +
 529                     "does not have RETAIN_CLASS_REFERENCE access");
 530         }
 531 
 532         return StackStreamFactory.makeCallerFinder(this).findCaller();
 533     }
 534 
 535     // ---- package access ----
 536     static StackWalker newInstanceNoCheck(EnumSet<Option> options) {
 537         return new StackWalker(options, 0, null);
 538     }
 539 
 540     static StackWalker newInstance(Set<Option> options, ExtendedOption extendedOption) {
 541         checkPermission(options);
 542         return new StackWalker(toEnumSet(options), 0, extendedOption);
 543     }
 544 
 545     int estimateDepth() {
 546         return estimateDepth;
 547     }
 548 
 549     boolean hasOption(Option option) {
 550         return options.contains(option);
 551     }
 552 
 553     boolean hasLocalsOperandsOption() {
 554         return extendedOption == ExtendedOption.LOCALS_AND_OPERANDS;
 555     }
 556 
 557     void ensureAccessEnabled(Option access) {
 558         if (!hasOption(access)) {
 559             throw new UnsupportedOperationException("No access to " + access +
 560                     ": " + options.toString());
 561         }
 562     }
 563 }