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.create(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.create().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 1.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 1.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 method represented
 104          *         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             return new StackTraceElement(getClassName(), getMethodName(),
 177                                          getFileName().orElse(null),
 178                                          getLineNumber().orElse(-1));
 179         }
 180     }
 181 
 182     /**
 183      * Stack walker option to configure the {@linkplain StackFrame stack frame}
 184      * information obtained by a {@code StackWalker}.
 185      *
 186      * @since 1.9
 187      */
 188     public enum Option {
 189         /**
 190          * Retains {@code Class} object in {@code StackFrame}s
 191          * walked by this {@code StackWalker}.
 192          *
 193          * <p> A {@code StackWalker} configured with this option will support
 194          * {@link StackWalker#getCallerClass()} and
 195          * {@link StackFrame#getDeclaringClass() StackFrame.getDeclaringClass()}.
 196          */
 197         RETAIN_CLASS_REFERENCE,
 198         /**
 199          * Shows all reflection frames.
 200          *
 201          * <p>By default, reflection frames are hidden.  This includes the
 202          * {@link java.lang.reflect.Method#invoke} method
 203          * and the reflection implementation classes. A {@code StackWalker} with
 204          * this {@code SHOW_REFLECT_FRAMES} option will show all reflection frames.
 205          * The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all
 206          * reflection frames and it will also show other hidden frames that
 207          * are implementation-specific.
 208          */
 209         SHOW_REFLECT_FRAMES,
 210         /**
 211          * Shows all hidden frames.
 212          *
 213          * <p>A Java Virtual Machine implementation may hide implementation
 214          * specific frames in addition to {@linkplain #SHOW_REFLECT_FRAMES
 215          * reflection frames}. A {@code StackWalker} with this {@code SHOW_HIDDEN_FRAMES}
 216          * option will show all hidden frames (including reflection frames).
 217          */
 218         SHOW_HIDDEN_FRAMES;
 219     }
 220 
 221     enum ExtendedOption {
 222         /**
 223          * Obtain monitors, locals and operands.
 224          */
 225         LOCALS_AND_OPERANDS
 226     };
 227 
 228     static final EnumSet<Option> DEFAULT_EMPTY_OPTION = EnumSet.noneOf(Option.class);
 229 
 230     private final static StackWalker DEFAULT_WALKER =
 231         new StackWalker(DEFAULT_EMPTY_OPTION);
 232 
 233     private final Set<Option> options;
 234     private final ExtendedOption extendedOption;
 235     private final int estimateDepth;
 236 
 237     /**
 238      * Creates a {@code StackWalker} instance.
 239      *
 240      * <p> This {@code StackWalker} is configured to skip all
 241      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
 242      * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 243      *
 244      * @return a {@code StackWalker} configured to skip all
 245      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
 246      * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 247      *
 248      */
 249     public static StackWalker create() {
 250         // no permission check needed
 251         return DEFAULT_WALKER;
 252     }
 253 
 254     /**
 255      * Creates a {@code StackWalker} instance with the given option specifying
 256      * the stack frame information it can access.
 257      *
 258      * <p>
 259      * If a security manager is present and the given {@code option} is
 260      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 261      * it calls its {@link SecurityManager#checkPermission checkPermission}
 262      * method for {@code StackFramePermission("retainClassReference")}.
 263      *
 264      * @param option {@link Option stack walking option}
 265      *
 266      * @return a {@code StackWalker} configured with the given option
 267      *
 268      * @throws SecurityException if a security manager exists and its
 269      *         {@code checkPermission} method denies access.
 270      */
 271     public static StackWalker create(Option option) {
 272         return create(EnumSet.of(Objects.requireNonNull(option)));
 273     }
 274 
 275     /**
 276      * Creates a {@code StackWalker} instance with the given {@ocde options} specifying
 277      * the stack frame information it can access.  If the given {@ocde options}
 278      * is empty, this {@code StackWalker} is configured to skip all
 279      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
 280      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 281      *
 282      * <p>
 283      * If a security manager is present and the given {@code options} contains
 284      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 285      * it calls its {@link SecurityManager#checkPermission checkPermission}
 286      * method for {@code StackFramePermission("retainClassReference")}.
 287      *
 288      * @param options {@link Option stack walking option}
 289      *
 290      * @return a {@code StackWalker} configured with the given options
 291      *
 292      * @throws SecurityException if a security manager exists and its
 293      *         {@code checkPermission} method denies access.
 294      */
 295     public static StackWalker create(Set<Option> options) {
 296         if (options.isEmpty()) {
 297             return DEFAULT_WALKER;
 298         }
 299 
 300         checkPermission(options);
 301         return new StackWalker(toEnumSet(options));
 302     }
 303 
 304     /**
 305      * Creates a {@code StackWalker} instance with the given {@ocde options} specifying
 306      * the stack frame information it can access. If the given {@ocde options}
 307      * is empty, this {@code StackWalker} is configured to skip all
 308      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
 309      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
 310      *
 311      * <p>
 312      * If a security manager is present and the given {@code options} contains
 313      * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
 314      * it calls its {@link SecurityManager#checkPermission checkPermission}
 315      * method for {@code StackFramePermission("retainClassReference")}.
 316      *
 317      * <p>
 318      * The {@code estimateDepth} specifies the estimate number of stack frames
 319      * this {@code StackWalker} will traverse that the {@code StackWalker} could
 320      * use as a hint for the buffer size.
 321      *
 322      * @param options {@link Option stack walking options}
 323      * @param estimateDepth Estimate number of stack frames to be traversed.
 324      *
 325      * @return a {@code StackWalker} configured with the given options
 326      *
 327      * @throws IllegalArgumentException if {@code estimateDepth <= 0}
 328      * @throws SecurityException if a security manager exists and its
 329      *         {@code checkPermission} method denies access.
 330      */
 331     public static StackWalker create(Set<Option> options, int estimateDepth) {
 332         if (estimateDepth <= 0) {
 333             throw new IllegalArgumentException("estimateDepth must be > 0");
 334         }
 335         checkPermission(options);
 336         return new StackWalker(toEnumSet(options), estimateDepth);
 337     }
 338 
 339     // ----- private constructors ------
 340     private StackWalker(EnumSet<Option> options) {
 341         this(options, 0, null);
 342     }
 343     private StackWalker(EnumSet<Option> options, int estimateDepth) {
 344         this(options, estimateDepth, null);
 345     }
 346     private StackWalker(EnumSet<Option> options, int estimateDepth, ExtendedOption extendedOption) {
 347         this.options = options;
 348         this.estimateDepth = estimateDepth;
 349         this.extendedOption = extendedOption;
 350     }
 351 
 352     private static void checkPermission(Set<Option> options) {
 353         Objects.requireNonNull(options);
 354         SecurityManager sm = System.getSecurityManager();
 355         if (sm != null) {
 356             if (options.contains(Option.RETAIN_CLASS_REFERENCE)) {
 357                 sm.checkPermission(new StackFramePermission("retainClassReference"));
 358             }
 359         }
 360     }
 361 
 362     /*
 363      * Returns a defensive copy
 364      */
 365     private static EnumSet<Option> toEnumSet(Set<Option> options) {
 366         Objects.requireNonNull(options);
 367         if (options.isEmpty()) {
 368             return DEFAULT_EMPTY_OPTION;
 369         } else {
 370             return EnumSet.copyOf(options);
 371         }
 372     }
 373 
 374     /**
 375      * Applies the given function to the stream of {@code StackFrame}s
 376      * for the current thread, traversing from the top frame of the stack,
 377      * which is the method calling this {@code walk} method.
 378      *
 379      * <p>The {@code StackFrame} stream will be closed when
 380      * this method returns.  When a closed {@code Stream<StackFrame>} object
 381      * is reused, {@code IllegalStateException} will be thrown.
 382      *
 383      * @apiNote
 384      * For example, to find the first 10 calling frames, first skipping those frames
 385      * whose declaring class is in package {@code com.foo}:
 386      * <blockquote>
 387      * <pre>{@code
 388      * List<StackFrame> frames = StackWalker.create().walk(s ->
 389      *     s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
 390      *      .limit(10)
 391      *      .collect(Collectors.toList()));
 392      * }</pre></blockquote>
 393      *
 394      * <p>This method takes a {@code Function} accepting a {@code Stream<StackFrame>},
 395      * rather than returning a {@code Stream<StackFrame>} and allowing the
 396      * caller to directly manipulate the stream. The Java virtual machine is
 397      * free to reorganize a thread's control stack, for example, via
 398      * deoptimization. By taking a {@code Function} parameter, this method
 399      * allows access to stack frames through a stable view of a thread's control
 400      * stack.
 401      *
 402      * <p>Parallel execution is effectively disabled and stream pipeline
 403      * execution will only occur on the current thread.
 404      *
 405      * @implNote The implementation stabilizes the stack by anchoring a frame
 406      * specific to the stack walking and ensures that the stack walking is
 407      * performed above the anchored frame. When the stream object is closed or
 408      * being reused, {@code IllegalStateException} will be thrown.
 409      *
 410      * @param function a function that takes a stream of
 411      *                 {@linkplain StackFrame stack frames} and returns a result.
 412      * @param <T> The type of the result of applying the function to the
 413      *            stream of {@linkplain StackFrame stack frame}.
 414      *
 415      * @return the result of applying the function to the stream of
 416      *         {@linkplain StackFrame stack frame}.
 417      */
 418     @CallerSensitive
 419     public <T> T walk(Function<? super Stream<StackFrame>, ? extends T> function) {
 420         // Returning a Stream<StackFrame> would be unsafe, as the stream could
 421         // be used to access the stack frames in an uncontrolled manner.  For
 422         // example, a caller might pass a Spliterator of stack frames after one
 423         // or more frames had been traversed. There is no robust way to detect
 424         // whether the execution point when
 425         // Spliterator.tryAdvance(java.util.function.Consumer<? super T>) is
 426         // invoked is the exact same execution point where the stack frame
 427         // traversal is expected to resume.
 428 
 429         Objects.requireNonNull(function);
 430         return StackStreamFactory.makeStackTraverser(this, function)
 431                                  .walk();
 432     }
 433 
 434     /**
 435      * Performs the given action on each element of {@code StackFrame} stream
 436      * of the current thread, traversing from the top frame of the stack,
 437      * which is the method calling this {@code forEach} method.
 438      *
 439      * <p> This method is equivalent to calling
 440      * <blockquote>
 441      * {@code walk(s -> { s.forEach(action); return null; });}
 442      * </blockquote>
 443      *
 444      * @param action an action to be performed on each {@code StackFrame}
 445      *               of the stack of the current thread
 446      */
 447     @CallerSensitive
 448     public void forEach(Consumer<? super StackFrame> action) {
 449         Objects.requireNonNull(action);
 450         StackStreamFactory.makeStackTraverser(this, s -> {
 451             s.forEach(action);
 452             return null;
 453         }).walk();
 454     }
 455 
 456     /**
 457      * Gets the {@code Class} object of the caller invoking the method
 458      * that calls this {@code getCallerClass} method, if present; otherwise,
 459      * this method returns an empty {@code Optional}.
 460      * This is equivalent to calling
 461      * <pre>{@code
 462      *     walk(s -> s.map(StackFrame::getDeclaringClass)
 463      *                .filter(c -> isCallerClass(c))
 464      *                .skip(2)
 465      *                .findFirst());
 466      * }</pre>
 467      *
 468      * where {@code isCallerClass} filters out reflection frames,
 469      * {@link java.lang.invoke.MethodHandle} and hidden frames as this walker
 470      * may be configured with {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES}
 471      * or {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} option.
 472      *
 473      * @apiNote
 474      * For example, {@code ResourceBundleUtil::getBundle} loads a resource bundle
 475      * on behalf of the caller.  It calls this {@code getCallerClass} method
 476      * to find the method calling {@code Util::getResourceBundle} and use the caller's
 477      * class loader to load the resource bundle. The caller class in this example
 478      * is the {@code MyTool} class.
 479      *
 480      * <pre>{@code
 481      *     class ResourceBundleUtil {
 482      *         private final StackWalker walker = StackWalker.create(Option.RETAIN_CLASS_REFERENCE);
 483      *         public ResourceBundle getBundle(String bundleName) {
 484      *             Class<?> caller = walker.getCallerClass();
 485      *             return ResourceBundle.getBundle(bundleName, caller.getClassLoader());
 486      *         }
 487      *     }
 488      *
 489      *     class MyTool {
 490      *         private void init() {
 491      *             ResourceBundle rb = Util.getResourceBundle("mybundle");
 492      *         }
 493      *     }
 494      * }</pre>
 495      *
 496      * <p> If this {@code getCallerClass} method is called by the last frame
 497      * on the stack, when this {@code getCallerClass} method is
 498      * invoked from the {@code static main} entry point or
 499      * a method called from a JNI attached thread such as {@code Thread::run},
 500      * this method returns an empty {@code Optional} since
 501      * the caller's class is not found.
 502      *
 503      * <p> As illustrated in the example below, the {@code getCallerClass} method
 504      * is called from {@code Main::main} which is the last frame on stack.
 505      * {@link Optional#isPresent() caller.isPresent()}
 506      * returns {@code false} as {@code caller} is an empty optional.
 507      *
 508      * <pre>{@code
 509      *     public class Main {
 510      *         public static void main(String[] args) throws Exception {
 511      *             Optional<Class<?>> caller =
 512      *                 StackWalker.create(Option.RETAIN_CLASS_REFERENCE)
 513      *                            .getCallerClass();
 514      *             assert !caller.isPresent();
 515      *        }
 516      *    }
 517      * }</pre>
 518      *
 519      * @return {@code Class} object of the caller's caller invoking this method;
 520      * or an empty {@code Optional} if the caller's caller is not present.
 521      *
 522      * @throws UnsupportedOperationException if this {@code StackWalker}
 523      *         is not configured with {@link Option#RETAIN_CLASS_REFERENCE
 524      *         Option.RETAIN_CLASS_REFERENCE}.
 525      */
 526     @CallerSensitive
 527     public Optional<Class<?>> getCallerClass() {
 528         if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) {
 529             throw new UnsupportedOperationException("This stack walker " +
 530                     "does not have RETAIN_CLASS_REFERENCE access");
 531         }
 532 
 533         return StackStreamFactory.makeCallerFinder(this).findCaller();
 534     }
 535 
 536     // ---- package access ----
 537     static StackWalker newInstanceNoCheck(EnumSet<Option> options) {
 538         return new StackWalker(options, 0, null);
 539     }
 540 
 541     static StackWalker newInstance(Set<Option> options, ExtendedOption extendedOption) {
 542         checkPermission(options);
 543         return new StackWalker(toEnumSet(options), 0, extendedOption);
 544     }
 545 
 546     int estimateDepth() {
 547         return estimateDepth;
 548     }
 549 
 550     boolean hasOption(Option option) {
 551         return options.contains(option);
 552     }
 553 
 554     boolean hasLocalsOperandsOption() {
 555         return extendedOption == ExtendedOption.LOCALS_AND_OPERANDS;
 556     }
 557 
 558     void ensureAccessEnabled(Option access) {
 559         if (!hasOption(access)) {
 560             throw new UnsupportedOperationException("No access to " + access +
 561                     ": " + options.toString());
 562         }
 563     }
 564 }