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.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#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 300 /** 301 * Returns a {@code StackWalker} instance. 302 * 303 * <p> This {@code StackWalker} is configured to skip all 304 * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and 305 * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained. 306 * 307 * @return a {@code StackWalker} configured to skip all 308 * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and 309 * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained. 310 * 311 */ 312 public static StackWalker getInstance() { 313 // no permission check needed 314 return DEFAULT_WALKER; 315 } 316 317 /** 318 * Returns a {@code StackWalker} instance with the given option specifying 319 * the stack frame information it can access. 320 * 321 * <p> 322 * If a security manager is present and the given {@code option} is 323 * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE}, 324 * it calls its {@link SecurityManager#checkPermission checkPermission} 325 * method for {@code RuntimePermission("getStackWalkerWithClassReference")}. 326 * 327 * @param option {@link Option stack walking option} 328 * 329 * @return a {@code StackWalker} configured with the given option 330 * 331 * @throws SecurityException if a security manager exists and its 332 * {@code checkPermission} method denies access. 333 */ 334 public static StackWalker getInstance(Option option) { 335 return getInstance(EnumSet.of(Objects.requireNonNull(option))); 336 } 337 338 /** 339 * Returns a {@code StackWalker} instance with the given {@code options} specifying 340 * the stack frame information it can access. If the given {@code options} 341 * is empty, this {@code StackWalker} is configured to skip all 342 * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no 343 * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained. 344 * 345 * <p> 346 * If a security manager is present and the given {@code options} contains 347 * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE}, 348 * it calls its {@link SecurityManager#checkPermission checkPermission} 349 * method for {@code RuntimePermission("getStackWalkerWithClassReference")}. 350 * 351 * @param options {@link Option stack walking option} 352 * 353 * @return a {@code StackWalker} configured with the given options 354 * 355 * @throws SecurityException if a security manager exists and its 356 * {@code checkPermission} method denies access. 357 */ 358 public static StackWalker getInstance(Set<Option> options) { 359 if (options.isEmpty()) { 360 return DEFAULT_WALKER; 361 } 362 363 EnumSet<Option> optionSet = toEnumSet(options); 364 checkPermission(optionSet); 365 return new StackWalker(optionSet); 366 } 367 368 /** 369 * Returns a {@code StackWalker} instance with the given {@code options} specifying 370 * the stack frame information it can access. If the given {@code options} 371 * is empty, this {@code StackWalker} is configured to skip all 372 * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no 373 * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained. 374 * 375 * <p> 376 * If a security manager is present and the given {@code options} contains 377 * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE}, 378 * it calls its {@link SecurityManager#checkPermission checkPermission} 379 * method for {@code RuntimePermission("getStackWalkerWithClassReference")}. 380 * 381 * <p> 382 * The {@code estimateDepth} specifies the estimate number of stack frames 383 * this {@code StackWalker} will traverse that the {@code StackWalker} could 384 * use as a hint for the buffer size. 385 * 386 * @param options {@link Option stack walking options} 387 * @param estimateDepth Estimate number of stack frames to be traversed. 388 * 389 * @return a {@code StackWalker} configured with the given options 390 * 391 * @throws IllegalArgumentException if {@code estimateDepth <= 0} 392 * @throws SecurityException if a security manager exists and its 393 * {@code checkPermission} method denies access. 394 */ 395 public static StackWalker getInstance(Set<Option> options, int estimateDepth) { 396 if (estimateDepth <= 0) { 397 throw new IllegalArgumentException("estimateDepth must be > 0"); 398 } 399 EnumSet<Option> optionSet = toEnumSet(options); 400 checkPermission(optionSet); 401 return new StackWalker(optionSet, estimateDepth); 402 } 403 404 // ----- private constructors ------ 405 private StackWalker(EnumSet<Option> options) { 406 this(options, 0, null); 407 } 408 private StackWalker(EnumSet<Option> options, int estimateDepth) { 409 this(options, estimateDepth, null); 410 } 411 private StackWalker(EnumSet<Option> options, int estimateDepth, ExtendedOption extendedOption) { 412 this.options = options; 413 this.estimateDepth = estimateDepth; 414 this.extendedOption = extendedOption; 415 } 416 417 private static void checkPermission(Set<Option> options) { 418 Objects.requireNonNull(options); 419 SecurityManager sm = System.getSecurityManager(); 420 if (sm != null) { 421 if (options.contains(Option.RETAIN_CLASS_REFERENCE)) { 422 sm.checkPermission(new RuntimePermission("getStackWalkerWithClassReference")); 423 } 424 } 425 } 426 427 /* 428 * Returns a defensive copy 429 */ 430 private static EnumSet<Option> toEnumSet(Set<Option> options) { 431 Objects.requireNonNull(options); 432 if (options.isEmpty()) { 433 return DEFAULT_EMPTY_OPTION; 434 } else { 435 return EnumSet.copyOf(options); 436 } 437 } 438 439 /** 440 * Applies the given function to the stream of {@code StackFrame}s 441 * for the current thread, traversing from the top frame of the stack, 442 * which is the method calling this {@code walk} method. 443 * 444 * <p>The {@code StackFrame} stream will be closed when 445 * this method returns. When a closed {@code Stream<StackFrame>} object 446 * is reused, {@code IllegalStateException} will be thrown. 447 * 448 * @apiNote 449 * For example, to find the first 10 calling frames, first skipping those frames 450 * whose declaring class is in package {@code com.foo}: 451 * <blockquote> 452 * <pre>{@code 453 * List<StackFrame> frames = StackWalker.getInstance().walk(s -> 454 * s.dropWhile(f -> f.getClassName().startsWith("com.foo.")) 455 * .limit(10) 456 * .collect(Collectors.toList())); 457 * }</pre></blockquote> 458 * 459 * <p>This method takes a {@code Function} accepting a {@code Stream<StackFrame>}, 460 * rather than returning a {@code Stream<StackFrame>} and allowing the 461 * caller to directly manipulate the stream. The Java virtual machine is 462 * free to reorganize a thread's control stack, for example, via 463 * deoptimization. By taking a {@code Function} parameter, this method 464 * allows access to stack frames through a stable view of a thread's control 465 * stack. 466 * 467 * <p>Parallel execution is effectively disabled and stream pipeline 468 * execution will only occur on the current thread. 469 * 470 * @implNote The implementation stabilizes the stack by anchoring a frame 471 * specific to the stack walking and ensures that the stack walking is 472 * performed above the anchored frame. When the stream object is closed or 473 * being reused, {@code IllegalStateException} will be thrown. 474 * 475 * @param function a function that takes a stream of 476 * {@linkplain StackFrame stack frames} and returns a result. 477 * @param <T> The type of the result of applying the function to the 478 * stream of {@linkplain StackFrame stack frame}. 479 * 480 * @return the result of applying the function to the stream of 481 * {@linkplain StackFrame stack frame}. 482 */ 483 @CallerSensitive 484 public <T> T walk(Function<? super Stream<StackFrame>, ? extends T> function) { 485 // Returning a Stream<StackFrame> would be unsafe, as the stream could 486 // be used to access the stack frames in an uncontrolled manner. For 487 // example, a caller might pass a Spliterator of stack frames after one 488 // or more frames had been traversed. There is no robust way to detect 489 // whether the execution point when 490 // Spliterator.tryAdvance(java.util.function.Consumer<? super T>) is 491 // invoked is the exact same execution point where the stack frame 492 // traversal is expected to resume. 493 494 Objects.requireNonNull(function); 495 return StackStreamFactory.makeStackTraverser(this, function) 496 .walk(); 497 } 498 499 /** 500 * Performs the given action on each element of {@code StackFrame} stream 501 * of the current thread, traversing from the top frame of the stack, 502 * which is the method calling this {@code forEach} method. 503 * 504 * <p> This method is equivalent to calling 505 * <blockquote> 506 * {@code walk(s -> { s.forEach(action); return null; });} 507 * </blockquote> 508 * 509 * @param action an action to be performed on each {@code StackFrame} 510 * of the stack of the current thread 511 */ 512 @CallerSensitive 513 public void forEach(Consumer<? super StackFrame> action) { 514 Objects.requireNonNull(action); 515 StackStreamFactory.makeStackTraverser(this, s -> { 516 s.forEach(action); 517 return null; 518 }).walk(); 519 } 520 521 /** 522 * Gets the {@code Class} object of the caller who invoked the method 523 * that invoked {@code getCallerClass}. 524 * 525 * <p> This method filters {@linkplain Option#SHOW_REFLECT_FRAMES reflection 526 * frames}, {@link java.lang.invoke.MethodHandle}, and 527 * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} regardless of the 528 * {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES} 529 * and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options 530 * this {@code StackWalker} has been configured with. 531 * 532 * <p> This method should be called when a caller frame is present. If 533 * it is called from the bottom most frame on the stack, 534 * {@code IllegalCallerException} will be thrown. 535 * 536 * <p> This method throws {@code UnsupportedOperationException} 537 * if this {@code StackWalker} is not configured with the 538 * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option. 539 * 540 * @apiNote 541 * For example, {@code Util::getResourceBundle} loads a resource bundle 542 * on behalf of the caller. It invokes {@code getCallerClass} to identify 543 * the class whose method called {@code Util::getResourceBundle}. 544 * Then, it obtains the class loader of that class, and uses 545 * the class loader to load the resource bundle. The caller class 546 * in this example is {@code MyTool}. 547 * 548 * <pre>{@code 549 * class Util { 550 * private final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE); 551 * public ResourceBundle getResourceBundle(String bundleName) { 552 * Class<?> caller = walker.getCallerClass(); 553 * return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader()); 554 * } 555 * } 556 * 557 * class MyTool { 558 * private final Util util = new Util(); 559 * private void init() { 560 * ResourceBundle rb = util.getResourceBundle("mybundle"); 561 * } 562 * } 563 * }</pre> 564 * 565 * An equivalent way to find the caller class using the 566 * {@link StackWalker#walk walk} method is as follows 567 * (filtering the reflection frames, {@code MethodHandle} and hidden frames 568 * not shown below): 569 * <pre>{@code 570 * Optional<Class<?>> caller = walker.walk(s -> 571 * s.map(StackFrame::getDeclaringClass) 572 * .skip(2) 573 * .findFirst()); 574 * }</pre> 575 * 576 * When the {@code getCallerClass} method is called from a method that 577 * is the bottom most frame on the stack, 578 * for example, {@code static public void main} method launched by the 579 * {@code java} launcher, or a method invoked from a JNI attached thread, 580 * {@code IllegalCallerException} is thrown. 581 * 582 * @return {@code Class} object of the caller's caller invoking this method. 583 * 584 * @throws UnsupportedOperationException if this {@code StackWalker} 585 * is not configured with {@link Option#RETAIN_CLASS_REFERENCE 586 * Option.RETAIN_CLASS_REFERENCE}. 587 * @throws IllegalCallerException if there is no caller frame, i.e. 588 * when this {@code getCallerClass} method is called from a method 589 * which is the last frame on the stack. 590 */ 591 @CallerSensitive 592 public Class<?> getCallerClass() { 593 if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) { 594 throw new UnsupportedOperationException("This stack walker " + 595 "does not have RETAIN_CLASS_REFERENCE access"); 596 } 597 598 return StackStreamFactory.makeCallerFinder(this).findCaller(); 599 } 600 601 // ---- package access ---- 602 603 static StackWalker newInstance(Set<Option> options, ExtendedOption extendedOption) { 604 EnumSet<Option> optionSet = toEnumSet(options); 605 checkPermission(optionSet); 606 return new StackWalker(optionSet, 0, extendedOption); 607 } 608 609 int estimateDepth() { 610 return estimateDepth; 611 } 612 613 boolean hasOption(Option option) { 614 return options.contains(option); 615 } 616 617 boolean hasLocalsOperandsOption() { 618 return extendedOption == ExtendedOption.LOCALS_AND_OPERANDS; 619 } 620 621 void ensureAccessEnabled(Option access) { 622 if (!hasOption(access)) { 623 throw new UnsupportedOperationException("No access to " + access + 624 ": " + options.toString()); 625 } 626 } 627 }