src/share/classes/java/lang/Thread.java
Print this page
*** 34,43 ****
--- 34,46 ----
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
+ import java.util.function.Consumer;
+ import java.util.function.Function;
+ import java.util.function.Predicate;
import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
*** 1589,1598 ****
--- 1592,1717 ----
// else terminated so we don't put it in the map
}
return m;
}
+ // package-private
+ static void checkStackWalkPermission() {
+ // ## should it define a new "walkStack" permission?
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkPermission(
+ SecurityConstants.GET_STACK_TRACE_PERMISSION);
+ }
+ }
+
+ private static int MAX_STACK_DEPTH = 1024;
+ /**
+ * Performs the given action for each {@linkplain StackFrameInfo stack frame}
+ * of the current thread.
+ * <p>
+ * The first stack frame is the top of the stack, which is the
+ * last method invocation in the sequence. Some virtual machines may,
+ * under some circumstances, omit one or more stack frames
+ * from the stack trace.
+ *
+ * @param action a consumer traversing a stream of StackFrameInfo
+ * @param depthLimit maximum number of frames traversed
+ * @throws SecurityException if a security manager exists and its
+ * {@code checkPermission} method denies access to traverse stack.
+ *
+ * @since 1.8
+ */
+ public static void walkStack(Consumer<StackFrameInfo> action) {
+ checkStackWalkPermission();
+ StackStream.build(MAX_STACK_DEPTH).walk(action);
+ }
+
+ /**
+ * Performs the given action for each {@linkplain StackFrameInfo stack frame}
+ * of the current thread. This method traverses a maximum number of
+ * {@code depthLimit} frames.
+ * <p>
+ * The first stack frame is the top of the stack, which is the
+ * last method invocation in the sequence. Some virtual machines may,
+ * under some circumstances, omit one or more stack frames from the stack trace.
+ *
+ * @param action a consumer traversing a stream of StackFrameInfo
+ * @param depthLimit maximum number of frames traversed
+ * @throws SecurityException if a security manager exists and its
+ * {@code checkPermission} method denies access to traverse stack.
+ *
+ * @since 1.8
+ */
+ public static void walkStack(Consumer<StackFrameInfo> action, int depthLimit) {
+ checkStackWalkPermission();
+ StackStream.build(depthLimit).walk(action);
+ }
+
+ /**
+ * Performs the given action for the {@linkplain StackFrameInfo stack frames}
+ * of the current thread that match the given predicate. This method
+ * traverses a maximum number of {@code depthLimit} frames.
+ *
+ * @param predicate a predicate to apply to the stack walk
+ * @param action a consumer traversing a stream of StackFrameInfo
+ * @param depthLimit maximum number of frames traversed
+ *
+ * @throws SecurityException if a security manager exists and its
+ * {@code checkPermission} method denies access to traverse stack.
+ *
+ * @since 1.8
+ */
+ public static void walkStack(Predicate<StackFrameInfo> predicate,
+ Consumer<StackFrameInfo> action,
+ int depthLimit) {
+ checkStackWalkPermission();
+ StackStream.build(depthLimit).walk(predicate, action);
+ }
+
+ /**
+ * Returns the result of applying the given function to
+ * the caller frame that invokes the method calling this method.
+ * The stack frames associated with {@code java.lang.reflect.Method#invoke
+ * reflection} and its implementation are ignored.
+ *
+ * @param function a function to apply on the caller frame
+ *
+ * @return the result of applying the given function to
+ * the caller frame that invokes the method calling this method.
+ *
+ * @throws SecurityException if a security manager exists and its
+ * {@code checkPermission} method denies access to traverse stack.
+ */
+ public static <T> T getCaller(Function<StackFrameInfo,T> function) {
+ checkStackWalkPermission();
+ return StackStream.build(MAX_STACK_DEPTH).findCaller(function);
+ }
+
+ /**
+ * Returns the result of applying the given function to the first
+ * caller matching the given predicate and skipping
+ * the stack frames associated with {@linkplain java.lang.reflect.Method#invoke
+ * reflection} and its implementation.
+ * If there is no matching stack frame, {@code null} will be returned.
+ *
+ * @param predicate a predicate to apply to the stack walk
+ * @param function a function to apply on the first stack frame
+ * matching the given predicate
+ *
+ * @return the result of {@code function.apply(caller)} where {@code caller}
+ * is the first stack frame, skipping the reflection implementation,
+ * that matches the given predicate
+ *
+ * @throws SecurityException if a security manager exists and its
+ * {@code checkPermission} method denies access to traverse stack.
+ */
+ public static <T> T firstCaller(Predicate<StackFrameInfo> predicate,
+ Function<StackFrameInfo,T> function) {
+ checkStackWalkPermission();
+ return StackStream.build(MAX_STACK_DEPTH).findCaller(predicate, function);
+ }
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
new RuntimePermission("enableContextClassLoaderOverride");
/** cache of subclass security audit results */