oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.26k stars 1.62k forks source link

Add support for JCMD and the Attach API #8915

Open roberttoyonaga opened 4 months ago

roberttoyonaga commented 4 months ago

TL;DR

Support executing commands issued fromjcmd and support connection to SubstrateVM through the Attach API.

Motiviation

Native Image currently doesn't support jcmd. Currently, we work around this by relying on catching and handling Linux signals for many things. Examples include, generating heap dumps, dumping threads, generating NMT reports. JFR also cannot dynamically be controlled at runtime (unless JMX is used). Signals are not ideal because there are a limited number of usable signals. They are also not ideal because arguments cannot be specified. jcmd would solve these problems because it would allow for an unlimited number of commands and also allows for arguments.

Implementing the Attach API also opens the door to the possibility of other Java tools like jmap, jstack, etc being supported in the future.

Goals

Describe the solution you'd like.

Non-Goals

roberttoyonaga commented 4 months ago

I'm weighing the benefits of implementing this as uninterruptible vs interruptible. The implementation in OpenJDK is in native code: " The rationale for a pure native implementation is to be able to execute diagnostic commands even in critical situations like an out-of-memory condition. "

However, implementing this interruptibly would lower complexity by allowing for using java.nio.channels.SocketChannel to handle unix domain sockets and jdk.internal.misc.Signal for handling SIGQUIT (which kicks off the Attach API handshake).

Currently, handling signals for dumping thread stacks, or head dumps is interruptible. I am leaning toward implementing the Attach API and JCMD support interruptibly in Java. Are there any concerns about this?

fniephaus commented 4 months ago

I can help out with this.

Excellent, looking forward to your contribution, Robert! :)

Currently, handling signals for dumping thread stacks, or head dumps is interruptible. I am leaning toward implementing the Attach API and JCMD support interruptibly in Java. Are there any concerns about this?

Maybe @christianhaeubl has an opinion on this?

christianhaeubl commented 4 months ago

The implementation in OpenJDK is in native code.

If OpenJDK implements a feature fully in native code, it is pretty likely that we will need uninterruptible code (at least in the long run - we got bitten by that a couple times in the past). When implementing a prototype, it is definitely easier to use interruptible code though. Maybe, you can roughly sketch the steps that the attach API needs to execute, then it is easier to estimate if we have a reasonable chance with interruptible code.

roberttoyonaga commented 4 months ago

I was able to make a rough working prototype in interruptible Java using the high-level JDK features for handling sockets and signals. The general flow is:

So far, it doesn't seem like there are issues implementing it interruptably, especially since we already handle initiating dumping heap/threads interruptably. The actions to perform that we receive through jcmd can be uninterruptible, while the Attach API code itself is interruptible. However, it would mean we can't use jcmd in situations like OOM.

I could try and implement it uninterruptably to future proof it. In that case, I would copy how we handle SIGPROF, and try to use native code to handle the sockets.

christianhaeubl commented 4 months ago

Thanks! I guess the middle ground is to implement the infrastructure with interruptible code for now (that is probably much easier than using uninterruptible code). However, for the actual commands, we should enforce that they use uninterruptible code. If we ever run into issues, then we would only need to rewrite the infrastructure but not the individual commands.

roberttoyonaga commented 4 months ago

Ok, I think that's a good plan. I'll start with that. Thanks Christian!