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