RFR: JDK-8253001: [JVMCI] Add API for getting stacktraces independently of current thread
Erik Österlund
eosterlund at openjdk.java.net
Thu Sep 24 06:41:43 UTC 2020
On Wed, 23 Sep 2020 22:06:33 GMT, John R Rose <jrose at openjdk.org> wrote:
>> I'll let @chumer answer that question.
>>
>> However, I have another one of my own. As far as I can see, the only use of `java.lang.LiveStackFrame` and
>> `java.lang.LiveStackFrameInfo` in the JDK code base are in the
>> [LocalsAndOperands](https://github.com/openjdk/jdk/blob/6bab0f539fba8fb441697846347597b4a0ade428/test/jdk/java/lang/StackWalker/LocalsAndOperands.java)
>> test where they are used via reflection. Do you know if there are/were plans to make these classes public?
>
> The special case we support in the `StackWalker` API is intentionally limited, because a thread examining its own stack
> is the least risky and most performant scenario. The `StackWalker::walk` API point, in particular, is carefully
> designed so that its internal implementation can internally use unsafe "dangling" pointers from the thread into its own
> stack. This reduces copying and buffering, which is obviously the least expensive way to "take a quick peek" at what's
> on the stack. It is reasonable to ask to extend such functionality to a second, uncooperative thread, but this brings
> in lots of extra baggage:
> - How does the requesting thread get permission to look inside the target thread? (New security analysis.)
> - At what point does the target thread get its state taken as a snapshot? Any random moment?
> - How is the target thread "held still" while it is being sampled? (And then, "Where is this term 'safepoint' defined in
> the JVM specifications?")
> - Can a target thread refuse or defer the request, to defend some particular encapsulation?
> - How is that state stored, and what are the time and space costs for such storage?
> - What happens if the requesting thread just wants to look at a few bits? Do we still buffer up a whole backtrace?
> - Or, is the target thread required to execute callbacks provided by the requesting thread, with a temporary view, and if
> so, that limits are there on such callbacks?
> - Can the observation process ever cause the target thread to fail, or will any and all failures (OOME, SOE, etc.) be
> attributed to the requesting thread?
> - What happens if the requesting thread makes two requests in a row: Are there any guarantees about relations between
> the two sets of results? (To be fair, this is also an issue with the self-walking case.)
> - What happens if the requesting thread asks to change a value in a frame or pop or re-invoke or replace a frame? (Not
> allowed in the self-walking case either, but a plausible extension.)
>
> If only "just adding a thread parameter" were a straightforward extension… Instead, we have serious user model issues
> (see above), and serious implementation issues (see the PR).
> I think we could perhaps add cross-thread access to the current `StackWalker` API, if we came up with answers to the
> above. I think, in order to engineer it correctly, we would want to factor it as the composition of a self-walking
> request, *plus* a cross-call mechanism which would allow one thread to ask another thread to run a function. Jumbling
> these complex operations together into a big pile of new code would be the wrong way to do it. The self-walking API is
> pretty well understood, and there is a good literature on cross-call mechanisms too. Let's break the problem up.
> BTW, the current `StackWalker` API could certainly accept minor extensions to inspect locals, and/or to perform frame
> replacement, as hinted above. The JVM currently benefits from performing on-stack replacement when it can tell that a
> slow loop is worth (re-)optimizing as a fast loop. There's no reason the JDK libraries (say, the streams runtime, in
> particular) shouldn't have a shot at doing something similar. That would require internal JDK hooks self-inspect and
> replace loops with improved "customizations", on the fly.
>
> All of the above comments apply only to what might be called the self-inspecting, self-reflective, or "introspective"
> modes of stack walking. Debuggers usually don't do this (except in one-world environments like Lisp and SmallTalk),
> but rather operate from the side, through a privileged channel "under the virtual metal" like JVMTI. I suppose for
> those use cases, JVMTI is plenty good. If there is some trick for self-attachment (either direct or through a
> conspirator process), then some introspection is also possible, via JVMTI. For best performance, a more "one world"
> implementation is desirable, but this implies that we create a whole category of "debugging/monitoring code". Such
> debugging/monitoring code would (like today's runtime internals like those that use `Unsafe`) have privileges beyond
> regular application code. It might also have eBPF-like limitations on resource usage, so that its executions could be
> hidden "under the metal" of regular executions. IMO these are promising ideas. They might help us define a better,
> more cooperative debugging/monitoring primitives. I raise the ideas here because I think there may be a root issue
> here: How can we use the JDK's on-line introspection APIs for more purposes? How can we inject privileged monitoring
> code into Java executions? Adding yet another stack walking mechanism to the JVM seems to me like an inefficient way
> to move, a little bit, in the direction of cooperative debugging/monitoring facilities in the JDK. Conversely, if we
> can create a way to do (privileged) cross-calls, then we won't need yet another stack walking mechanism. I guess this
> is where I end up: Please consider refactoring this into an extension (if any is needed) to the self-inspection API
> (`StackWalker`) and something a cross-call API. Then we should consider hooking it up to JVMCI.
John there is a lot to be said here in the solution domain. But before we get there, I want to get answers about the
problem domain, so I know if we are solving a real or imaginary problem. The crucial question it boils down to is: "is
remote thread stack sampling with locals needed in the non-debugger case"? If so, we can start discussing the solution
domain of that. But I suspect we already have all the APIs in place that are needed.
-------------
PR: https://git.openjdk.java.net/jdk/pull/110
More information about the hotspot-compiler-dev
mailing list