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