1 /*
   2  * Copyright (c) 2015, 2016, 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 jdk.internal.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 index to the code array of the {@code Code} attribute
 131          * containing the execution point represented by this stack frame.
 132          * The code array gives the actual bytes of Java Virtual Machine code
 133          * that implement the method.
 134          *
 135          * @return the index to the code array of the {@code Code} attribute
 136          *         containing the execution point represented by this stack frame,
 137          *         or a negative number if the method is native.
 138          *
 139          * @jvms 4.7.3 The {@code Code} Attribute
 140          */
 141         public int getByteCodeIndex();
 142 
 143         /**
 144          * Returns the name of the source file containing the execution point
 145          * represented by this stack frame.  Generally, this corresponds
 146          * to the {@code SourceFile} attribute of the relevant {@code class}
 147          * file as defined by <cite>The Java Virtual Machine Specification</cite>.
 148          * In some systems, the name may refer to some source code unit
 149          * other than a file, such as an entry in a source repository.
 150          *
 151          * @return the name of the file containing the execution point
 152          *         represented by this stack frame, or {@code null} if
 153          *         this information is unavailable.
 154          *
 155          * @jvms 4.7.10 The {@code SourceFile} Attribute
 156          */
 157         public String getFileName();
 158 
 159         /**
 160          * Returns the line number of the source line containing the execution
 161          * point represented by this stack frame.  Generally, this is
 162          * derived from the {@code LineNumberTable} attribute of the relevant
 163          * {@code class} file as defined by <cite>The Java Virtual Machine
 164          * Specification</cite>.
 165          *
 166          * @return the line number of the source line containing the execution
 167          *         point represented by this stack frame, or a negative number if
 168          *         this information is unavailable.
 169          *
 170          * @jvms 4.7.12 The {@code LineNumberTable} Attribute
 171          */
 172         public int getLineNumber();
 173 
 174         /**
 175          * Returns {@code true} if the method containing the execution point
 176          * represented by this stack frame is a native method.
 177          *
 178          * @return {@code true} if the method containing the execution point
 179          *         represented by this stack frame is a native method.
 180          */
 181         public boolean isNativeMethod();
 182 
 183         /**
 184          * Gets a {@code StackTraceElement} for this stack frame.
 185          *
 186          * @return {@code StackTraceElement} for this stack frame.
 187          */
 188         public StackTraceElement toStackTraceElement();
 189     }
 190 
 191     /**
 192      * Stack walker option to configure the {@linkplain StackFrame stack frame}
 193      * information obtained by a {@code StackWalker}.
 194      *
 195      * @since 9
 196      */
 197     public enum Option {
 198         /**
 199          * Retains {@code Class} object in {@code StackFrame}s
 200          * walked by this {@code StackWalker}.
 201          *
 202          * <p> A {@code StackWalker} configured with this option will support
 203          * {@link StackWalker#getCallerClass()} and
 204          * {@link StackFrame#getDeclaringClass() StackFrame.getDeclaringClass()}.
 205          */
 206         RETAIN_CLASS_REFERENCE,
 207         /**
 208          * Shows all reflection frames.
 209          *
 210          * <p>By default, reflection frames are hidden.  This includes the
 211          * {@link java.lang.reflect.Method#invoke} method
 212          * and the reflection implementation classes. A {@code StackWalker} with
 213          * this {@code SHOW_REFLECT_FRAMES} option will show all reflection frames.
 214          * The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all
 215          * reflection frames and it will also show other hidden frames that
 216          * are implementation-specific.
 217          */
 218         SHOW_REFLECT_FRAMES,
 219         /**
 220          * Shows all hidden frames.
 221          *
 222          * <p>A Java Virtual Machine implementation may hide implementation
 223          * specific frames in addition to {@linkplain #SHOW_REFLECT_FRAMES
 224          * reflection frames}. A {@code StackWalker} with this {@code SHOW_HIDDEN_FRAMES}
 225          * option will show all hidden frames (including reflection frames).
 226          */
 227         SHOW_HIDDEN_FRAMES;
 228     }
 229 
 230     enum ExtendedOption {
 231         /**
 232          * Obtain monitors, locals and operands.
 233          */
 234         LOCALS_AND_OPERANDS
 235     };
 236 
 237     static final EnumSet<Option> DEFAULT_EMPTY_OPTION = EnumSet.noneOf(Option.class);
 238 
 239     private final static StackWalker DEFAULT_WALKER =
 240         new StackWalker(DEFAULT_EMPTY_OPTION);
 241 
 242     private final Set<Option> options;
 243     private final ExtendedOption extendedOption;
 244     private final int estimateDepth;
 245 
 246     /**
 247      * Returns a {@code StackWalker} instance.
 248      *
 249      * <p> This {@code StackWalker} is configured to skip all
 250      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
 251      * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 252      *
 253      * @return a {@code StackWalker} configured to skip all
 254      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
 255      * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 256      *
 257      */
 258     public static StackWalker getInstance() {
 259         // no permission check needed
 260         return DEFAULT_WALKER;
 261     }
 262 
 263     /**
 264      * Returns a {@code StackWalker} instance with the given option specifying
 265      * the stack frame information it can access.
 266      *
 267      * <p>
 268      * If a security manager is present and the given {@code option} is
 269      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 270      * it calls its {@link SecurityManager#checkPermission checkPermission}
 271      * method for {@code StackFramePermission("retainClassReference")}.
 272      *
 273      * @param option {@link Option stack walking option}
 274      *
 275      * @return a {@code StackWalker} configured with the given option
 276      *
 277      * @throws SecurityException if a security manager exists and its
 278      *         {@code checkPermission} method denies access.
 279      */
 280     public static StackWalker getInstance(Option option) {
 281         return getInstance(EnumSet.of(Objects.requireNonNull(option)));
 282     }
 283 
 284     /**
 285      * Returns a {@code StackWalker} instance with the given {@code options} specifying
 286      * the stack frame information it can access.  If the given {@code options}
 287      * is empty, this {@code StackWalker} is configured to skip all
 288      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
 289      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 290      *
 291      * <p>
 292      * If a security manager is present and the given {@code options} contains
 293      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 294      * it calls its {@link SecurityManager#checkPermission checkPermission}
 295      * method for {@code StackFramePermission("retainClassReference")}.
 296      *
 297      * @param options {@link Option stack walking option}
 298      *
 299      * @return a {@code StackWalker} configured with the given options
 300      *
 301      * @throws SecurityException if a security manager exists and its
 302      *         {@code checkPermission} method denies access.
 303      */
 304     public static StackWalker getInstance(Set<Option> options) {
 305         if (options.isEmpty()) {
 306             return DEFAULT_WALKER;
 307         }
 308 
 309         EnumSet<Option> optionSet = toEnumSet(options);
 310         checkPermission(optionSet);
 311         return new StackWalker(optionSet);
 312     }
 313 
 314     /**
 315      * Returns a {@code StackWalker} instance with the given {@code options} specifying
 316      * the stack frame information it can access. If the given {@code options}
 317      * is empty, this {@code StackWalker} is configured to skip all
 318      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
 319      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 320      *
 321      * <p>
 322      * If a security manager is present and the given {@code options} contains
 323      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 324      * it calls its {@link SecurityManager#checkPermission checkPermission}
 325      * method for {@code StackFramePermission("retainClassReference")}.
 326      *
 327      * <p>
 328      * The {@code estimateDepth} specifies the estimate number of stack frames
 329      * this {@code StackWalker} will traverse that the {@code StackWalker} could
 330      * use as a hint for the buffer size.
 331      *
 332      * @param options {@link Option stack walking options}
 333      * @param estimateDepth Estimate number of stack frames to be traversed.
 334      *
 335      * @return a {@code StackWalker} configured with the given options
 336      *
 337      * @throws IllegalArgumentException if {@code estimateDepth <= 0}
 338      * @throws SecurityException if a security manager exists and its
 339      *         {@code checkPermission} method denies access.
 340      */
 341     public static StackWalker getInstance(Set<Option> options, int estimateDepth) {
 342         if (estimateDepth <= 0) {
 343             throw new IllegalArgumentException("estimateDepth must be > 0");
 344         }
 345         EnumSet<Option> optionSet = toEnumSet(options);
 346         checkPermission(optionSet);
 347         return new StackWalker(optionSet, estimateDepth);
 348     }
 349 
 350     // ----- private constructors ------
 351     private StackWalker(EnumSet<Option> options) {
 352         this(options, 0, null);
 353     }
 354     private StackWalker(EnumSet<Option> options, int estimateDepth) {
 355         this(options, estimateDepth, null);
 356     }
 357     private StackWalker(EnumSet<Option> options, int estimateDepth, ExtendedOption extendedOption) {
 358         this.options = options;
 359         this.estimateDepth = estimateDepth;
 360         this.extendedOption = extendedOption;
 361     }
 362 
 363     private static void checkPermission(Set<Option> options) {
 364         Objects.requireNonNull(options);
 365         SecurityManager sm = System.getSecurityManager();
 366         if (sm != null) {
 367             if (options.contains(Option.RETAIN_CLASS_REFERENCE)) {
 368                 sm.checkPermission(new StackFramePermission("retainClassReference"));
 369             }
 370         }
 371     }
 372 
 373     /*
 374      * Returns a defensive copy
 375      */
 376     private static EnumSet<Option> toEnumSet(Set<Option> options) {
 377         Objects.requireNonNull(options);
 378         if (options.isEmpty()) {
 379             return DEFAULT_EMPTY_OPTION;
 380         } else {
 381             return EnumSet.copyOf(options);
 382         }
 383     }
 384 
 385     /**
 386      * Applies the given function to the stream of {@code StackFrame}s
 387      * for the current thread, traversing from the top frame of the stack,
 388      * which is the method calling this {@code walk} method.
 389      *
 390      * <p>The {@code StackFrame} stream will be closed when
 391      * this method returns.  When a closed {@code Stream<StackFrame>} object
 392      * is reused, {@code IllegalStateException} will be thrown.
 393      *
 394      * @apiNote
 395      * For example, to find the first 10 calling frames, first skipping those frames
 396      * whose declaring class is in package {@code com.foo}:
 397      * <blockquote>
 398      * <pre>{@code
 399      * List<StackFrame> frames = StackWalker.getInstance().walk(s ->
 400      *     s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
 401      *      .limit(10)
 402      *      .collect(Collectors.toList()));
 403      * }</pre></blockquote>
 404      *
 405      * <p>This method takes a {@code Function} accepting a {@code Stream<StackFrame>},
 406      * rather than returning a {@code Stream<StackFrame>} and allowing the
 407      * caller to directly manipulate the stream. The Java virtual machine is
 408      * free to reorganize a thread's control stack, for example, via
 409      * deoptimization. By taking a {@code Function} parameter, this method
 410      * allows access to stack frames through a stable view of a thread's control
 411      * stack.
 412      *
 413      * <p>Parallel execution is effectively disabled and stream pipeline
 414      * execution will only occur on the current thread.
 415      *
 416      * @implNote The implementation stabilizes the stack by anchoring a frame
 417      * specific to the stack walking and ensures that the stack walking is
 418      * performed above the anchored frame. When the stream object is closed or
 419      * being reused, {@code IllegalStateException} will be thrown.
 420      *
 421      * @param function a function that takes a stream of
 422      *                 {@linkplain StackFrame stack frames} and returns a result.
 423      * @param <T> The type of the result of applying the function to the
 424      *            stream of {@linkplain StackFrame stack frame}.
 425      *
 426      * @return the result of applying the function to the stream of
 427      *         {@linkplain StackFrame stack frame}.
 428      */
 429     @CallerSensitive
 430     public <T> T walk(Function<? super Stream<StackFrame>, ? extends T> function) {
 431         // Returning a Stream<StackFrame> would be unsafe, as the stream could
 432         // be used to access the stack frames in an uncontrolled manner.  For
 433         // example, a caller might pass a Spliterator of stack frames after one
 434         // or more frames had been traversed. There is no robust way to detect
 435         // whether the execution point when
 436         // Spliterator.tryAdvance(java.util.function.Consumer<? super T>) is
 437         // invoked is the exact same execution point where the stack frame
 438         // traversal is expected to resume.
 439 
 440         Objects.requireNonNull(function);
 441         return StackStreamFactory.makeStackTraverser(this, function)
 442                                  .walk();
 443     }
 444 
 445     /**
 446      * Performs the given action on each element of {@code StackFrame} stream
 447      * of the current thread, traversing from the top frame of the stack,
 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     }
 553 
 554     int estimateDepth() {
 555         return estimateDepth;
 556     }
 557 
 558     boolean hasOption(Option option) {
 559         return options.contains(option);
 560     }
 561 
 562     boolean hasLocalsOperandsOption() {
 563         return extendedOption == ExtendedOption.LOCALS_AND_OPERANDS;
 564     }
 565 
 566     void ensureAccessEnabled(Option access) {
 567         if (!hasOption(access)) {
 568             throw new UnsupportedOperationException("No access to " + access +
 569                     ": " + options.toString());
 570         }
 571     }
 572 }