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