/* * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang; import jdk.internal.reflect.CallerSensitive; import java.lang.invoke.MethodType; import java.util.EnumSet; import java.util.Objects; import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; import jdk.internal.vm.Continuation; import jdk.internal.vm.ContinuationScope; /** * A stack walker. * *
The {@link StackWalker#walk walk} method opens a sequential stream * of {@link StackFrame StackFrame}s for the current thread and then applies * the given function to walk the {@code StackFrame} stream. * The stream reports stack frame elements in order, from the top most frame * that represents the execution point at which the stack was generated to * the bottom most frame. * The {@code StackFrame} stream is closed when the {@code walk} method returns. * If an attempt is made to reuse the closed stream, * {@code IllegalStateException} will be thrown. * *
{@linkplain Option Stack walker options} configure the stack frame * information obtained by a {@code StackWalker}. * By default, the class name and method information are collected but * not the {@link StackFrame#getDeclaringClass() Class reference}. * The method information can be dropped via the {@link Option#DROP_METHOD_INFO * DROP_METHOD_INFO} option. The {@code Class} object can be retained for * access via the {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option. * Stack frames of the reflection API and implementation classes are * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden} by default. * *
{@code StackWalker} is thread-safe. Multiple threads can share * a single {@code StackWalker} object to traverse its own stack. * * @apiNote * Examples * *
1. To find the first caller filtering out a known list of implementation class:
* {@snippet lang="java" :
* StackWalker walker = StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE));
* Optional 2. To snapshot the top 10 stack frames of the current thread,
* {@snippet lang="java" :
* List {@linkplain Option Stack walker options} configure the stack
* frame information obtained by a {@code StackWalker}.
* If the stack walker is configured with {@link Option#DROP_METHOD_INFO
* DROP_METHOD_INFO} option, method information such as
* the {@linkplain StackFrame#getMethodName() method name},
* the {@linkplain StackFrame#getLineNumber() line number},
* the {@linkplain StackFrame#getByteCodeIndex() bytecode index}, etc
* will be dropped.
* If the stack walker is configured with {@link Option#RETAIN_CLASS_REFERENCE
* RETAIN_CLASS_REFERENCE} option, the {@link #getDeclaringClass() Class} object
* will be retained for access.
*
* @since 9
* @jvms 2.6 Frames
*/
public interface StackFrame {
/**
* {@return the {@linkplain ClassLoader##binary-name binary name}
* of the declaring class of the method represented by this stack frame}
*
* @jls 13.1 The Form of a Binary
*/
public String getClassName();
/**
* {@return the name of the method represented by this stack frame}
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option
*/
public String getMethodName();
/**
* {@return the declaring {@code Class} for the method represented by
* this stack frame}
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* without {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option
*/
public Class> getDeclaringClass();
/**
* Returns the {@link MethodType} representing the parameter types and
* the return type for the method represented by this stack frame.
*
* @implSpec
* The default implementation throws {@code UnsupportedOperationException}.
*
* @return the {@code MethodType} of the method represented by this stack frame
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option or
* without {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option
*
* @since 10
*/
public default MethodType getMethodType() {
throw new UnsupportedOperationException();
}
/**
* Returns the descriptor of the method represented by
* this stack frame as defined by
* The Java Virtual Machine Specification.
*
* @implSpec
* The default implementation throws {@code UnsupportedOperationException}.
*
* @return the descriptor of the method represented by
* this stack frame
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option
*
* @see MethodType#fromMethodDescriptorString(String, ClassLoader)
* @see MethodType#toMethodDescriptorString()
* @jvms 4.3.3 Method Descriptors
*
* @since 10
*/
public default String getDescriptor() {
throw new UnsupportedOperationException();
}
/**
* Returns the index to the code array of the {@code Code} attribute
* containing the execution point represented by this stack frame.
* The code array gives the actual bytes of Java Virtual Machine code
* that implement the method.
*
* @return the index to the code array of the {@code Code} attribute
* containing the execution point represented by this stack frame,
* or a negative number if the method is native.
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option
*
* @jvms 4.7.3 The {@code Code} Attribute
*/
public int getByteCodeIndex();
/**
* Returns the name of the source file containing the execution point
* represented by this stack frame. Generally, this corresponds
* to the {@code SourceFile} attribute of the relevant {@code class}
* file as defined by The Java Virtual Machine Specification.
* In some systems, the name may refer to some source code unit
* other than a file, such as an entry in a source repository.
*
* @return the name of the file containing the execution point
* represented by this stack frame, or {@code null} if
* this information is unavailable.
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option
*
* @jvms 4.7.10 The {@code SourceFile} Attribute
*/
public String getFileName();
/**
* Returns the line number of the source line containing the execution
* point represented by this stack frame. Generally, this is
* derived from the {@code LineNumberTable} attribute of the relevant
* {@code class} file as defined by The Java Virtual Machine
* Specification.
*
* @return the line number of the source line containing the execution
* point represented by this stack frame, or a negative number if
* this information is unavailable.
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option
*
* @jvms 4.7.12 The {@code LineNumberTable} Attribute
*/
public int getLineNumber();
/**
* {@return {@code true} if the method containing the execution point
* represented by this stack frame is a native method}
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option
*/
public boolean isNativeMethod();
/**
* {@return {@code StackTraceElement} for this stack frame}
*
* @throws UnsupportedOperationException if the {@code StackWalker} is configured
* with {@link Option#DROP_METHOD_INFO DROP_METHOD_INFO} option
*/
public StackTraceElement toStackTraceElement();
}
/**
* Stack walker option to configure the {@linkplain StackFrame stack frame}
* information obtained by a {@code StackWalker}.
*
* @since 9
*/
public enum Option {
/**
* Retains {@code Class} object in {@code StackFrame}s
* walked by this {@code StackWalker}.
*
* A {@code StackWalker} configured with this option will support
* {@link StackWalker#getCallerClass()} and
* {@link StackFrame#getDeclaringClass() StackFrame.getDeclaringClass()}.
*/
RETAIN_CLASS_REFERENCE,
/**
* Drops the method information from {@code StackFrame}s
* walked by this {@code StackWalker}.
*
* A {@code StackWalker} configured with this option will drop
* the {@linkplain StackFrame#getMethodName() method name},
* the {@linkplain StackFrame#getMethodType() method type},
* the {@linkplain StackFrame#getLineNumber() line number},
* the {@linkplain StackFrame#getByteCodeIndex() bytecode index},
* the {@linkplain StackFrame#getFileName() source file name} and
* {@linkplain StackFrame#isNativeMethod() native method or not}.
*
* @since 22
*/
DROP_METHOD_INFO,
/**
* Shows all reflection frames.
*
* By default, reflection frames are hidden. A {@code StackWalker}
* configured with this {@code SHOW_REFLECT_FRAMES} option
* will show all reflection frames that
* include {@link java.lang.reflect.Method#invoke} and
* {@link java.lang.reflect.Constructor#newInstance(Object...)}
* and their reflection implementation classes.
*
* The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all
* reflection frames and it will also show other hidden frames that
* are implementation-specific.
*
* @apiNote
* This option includes the stack frames representing the invocation of
* {@code Method} and {@code Constructor}. Any utility methods that
* are equivalent to calling {@code Method.invoke} or
* {@code Constructor.newInstance} such as {@code Class.newInstance}
* are not filtered or controlled by any stack walking option.
*/
SHOW_REFLECT_FRAMES,
/**
* Shows all hidden frames.
*
* A Java Virtual Machine implementation may hide implementation
* specific frames in addition to {@linkplain #SHOW_REFLECT_FRAMES
* reflection frames}. A {@code StackWalker} with this {@code SHOW_HIDDEN_FRAMES}
* option will show all hidden frames (including reflection frames).
*/
SHOW_HIDDEN_FRAMES;
}
enum ExtendedOption {
/**
* Obtain monitors, locals and operands.
*/
LOCALS_AND_OPERANDS
};
static final EnumSet