On Fri, 25 Aug 2023 22:22:43 GMT, Mandy Chung <mch...@openjdk.org> wrote:
>> 8268829: Provide an optimized way to walk the stack with Class object only >> >> `StackWalker::walk` creates one `StackFrame` per frame and the current >> implementation >> allocates one `StackFrameInfo` and one `MemberName` objects per frame. Some >> frameworks >> like logging may only interest in the Class object but not the method name >> nor the BCI, >> for example, filters out its implementation classes to find the caller >> class. It's >> similar to `StackWalker::getCallerClass` but allows a predicate to filter >> out the element. >> >> This PR proposes to add `StackWalker.Kind` enum to specify the information >> that a stack walker >> collects. If no method information is needed, a `StackWalker` of >> `CLASS_INFO` can be used >> instead and such stack walker will save the overhead (1) to extract the >> method information >> and (2) the memory used for the stack walking. In addition, this can also >> fix >> >> - [8311500](https://bugs.openjdk.org/browse/JDK-8311500): >> StackWalker.getCallerClass() throws UOE if invoked reflectively >> >> New factory methods to take a parameter to specify the kind of stack walker >> to be created are defined. >> This provides a simple way for existing code, for example logging >> frameworks, to take advantage of >> this enhancement with the least change as it can keep the existing function >> for traversing >> `StackFrame`s. >> >> For example: to find the first caller filtering a known list of >> implementation class, >> existing code can call `StackWalker::getInstance(CLASS_INFO, ...)` to create >> a stack walker instance: >> >> >> StackWalker walker = StackWalker.getInstance(Kind.CLASS_INFO, >> Option.RETAIN_CLASS_REFERENCE); >> Optional<Class<?>> callerClass = walker.walk(s -> >> s.map(StackFrame::getDeclaringClass) >> .filter(interestingClasses::contains) >> .findFirst()); >> >> >> If method information is accessed on the `StackFrame`s produced by this >> stack walker such as >> `StackFrame::getMethodName`, then `UnsupportedOperationException` will be >> thrown. >> >> #### Javadoc & specdiff >> >> https://cr.openjdk.org/~mchung/api/java.base/java/lang/StackWalker.html >> https://cr.openjdk.org/~mchung/jdk22/specdiff/overview-summary.html >> >> #### Alternatives Considered >> One alternative is to provide a new API: >> `<T> T walkClass(Function<? super Stream<Class<?>, ? extends T> function)` >> >> In this case, the caller would need to pass a function that takes a stream >> of `Class` object instead of `StackFrame`. Existing code would hav... > > Mandy Chung has updated the pull request incrementally with two additional > commits since the last revision: > > - fixup javadoc > - Review feedback: move JLIA to ClassFrameInfo src/java.base/share/classes/java/lang/StackWalker.java line 81: > 79: * Optional<Class<?>> callerClass = walker.walk(s -> > 80: * s.map(StackFrame::getDeclaringClass) > 81: * .filter(interestingClasses::contains) Usually it's more `.filter(Predicate.not(implClasses::contains))` src/java.base/share/classes/java/lang/StackWalker.java line 88: > 86: * {@snippet lang="java" : > 87: * List<StackFrame> stack = StackWalker.getInstance().walk(s -> > 88: * s.limit(10).collect(Collectors.toList())); `s.limit(10).toList()` src/java.base/share/classes/java/lang/StackWalker.java line 505: > 503: */ > 504: public static StackWalker getInstance(Kind kind, Option... options) { > 505: return getInstance(Objects.requireNonNull(kind), > Set.of(Objects.requireNonNull(options))); Set.of() already does a NPE check src/java.base/share/classes/java/lang/StackWalker.java line 649: > 647: * s.dropWhile(f -> f.getClassName().startsWith("com.foo.")) > 648: * .limit(10) > 649: * .collect(Collectors.toList())); `.toList())` ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/15370#discussion_r1306390180 PR Review Comment: https://git.openjdk.org/jdk/pull/15370#discussion_r1306390266 PR Review Comment: https://git.openjdk.org/jdk/pull/15370#discussion_r1306390553 PR Review Comment: https://git.openjdk.org/jdk/pull/15370#discussion_r1306390713