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