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