RFR: JDK-8253001: [JVMCI] Add API for getting stacktraces independently of current thread

Allan Gregersen github.com+4676506+javeleon at openjdk.java.net
Thu Sep 24 10:42:17 UTC 2020


On Thu, 24 Sep 2020 08:02:13 GMT, Allan Gregersen <github.com+4676506+javeleon at openjdk.org> wrote:

>> 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.
>
> A lot of good comments here. Thanks!
> 
> I agree that we should look at the problem domain first. Hence, let's look at the use-cases that was brought up once
> more.
> 1. The Truffle debugger (not to be confused with a Java host debugger) in general needs to access all live stack traces
> for all guest-language threads and read/write access to local variables.
> 2. Some Truffle guest languages need to access all live objects (e.g. Ruby). Espresso also needs this for implementing
> e.g. getReferringObjects (through the debugger though) etc.
> Onto discussing potential solutions:
> 
> After discussing the capabilities of JVMTI internally, it seems that the current implementation of getting locals might
> not be able to return anything for escape-analyzed objects. This obviously poses a serious limitation for Truffle given
> the fact that this is a corner-stone in GraalVM. I take it this played a big role in introducing iterateFrames (current
> thread only) in JVMCI a while back.  Even for the debugger case we would need JVMTI to guarantee the following: 1. A
> safe suspension mechanism for all target threads (what if two debuggers are connected at the same time?) that would
> span the entirety of getAllStackTraces + fetching all locals for all frames. I don't see how something like
> suspendThreadList would provide the safe guards that we would need here. 2. A bulk getAllLocals to avoid fetching all
> stack traces + retrieving all locals in bulk for all frames.  Given that Truffle/GraalVM will continue to support Java
> 8 for quite some time, this new API should probably be exposed through JVMCI and backported like it was done for
> iterateFrames regardless of the underlying implementation.  Note: In the current PR we need to refactor
> materializeVirtualObjects into using VM operations to guarantee that we run stack walking and sanity checks for
> locating the frame in question at a safe point. I'll hold my horses a bit on that until there is a consensus on where
> this is going.

It’s important to note that this PR is about making changes to JVMCI which is internal API and not part of the JavaSE
API.

With that framing let's address the questions that came up:

- is remote thread stack sampling with locals needed in the non-debugger case?

Yes (see previous comment). What existing APIs are in place for this?

- How does the requesting thread get permission to look inside the target thread? (New security analysis.)

No permission needed - JVMCI is a privileged API that has “boot loader” access.

- At what point does the target thread get its state taken as a snapshot? Any random moment?

The snapshot of threads is taken at a safepoint (much like Thread.getAllStackTraces() which does not mention safepoints
either)

- How is the target thread “held still” while it is being sampled? (And then, “Where is this term ‘safepoint’ defined in
  the JVM specifications?“)

See above.

- Can a target thread refuse or defer the request, to defend some particular encapsulation?

No - see above.

- How is that state stored, and what are the time and space costs for such storage?

The state is stored within
[HotSpotStackFrameReference](https://github.com/openjdk/jdk/blob/master/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java)
instances. its about the same time and cost as java.lang.LiveStackFrameInfo.

- What happens if the requesting thread just wants to look at a few bits? Do we still buffer up a whole backtrace?

In the suggested API you can 1) limit the number of frames to capture, 2) skip the first N top frames 3) add an array
of methods as argument that any frames seen on stack before those are not included and 4) add an array of methods as
arguments controlling the exact methods to include in the result.

- 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?

No 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?

No. All failures will 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.)

No guarantees.

- 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.)

No support for this. The snapshot is read-only.

-------------

PR: https://git.openjdk.java.net/jdk/pull/110


More information about the hotspot-compiler-dev mailing list