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 */