RFR: 8275259: Add support for Java level DCmd [v2]

Denghui Dong ddong at openjdk.java.net
Mon Oct 25 06:45:00 UTC 2021


On Fri, 15 Oct 2021 10:58:29 GMT, Denghui Dong <ddong at openjdk.org> wrote:

>> I proposed to extend DCmd to allow Java developers to customize their own diagnostic commands last week.
>> 
>> At present, I have implemented a preliminary version.
>> 
>> In the current implementation, I provided some simple APIs in the Java layer (under sun.management.cmd) for defining and registering commands.
>> 
>> - Executable interface
>>   Java diagnostic commands need to implement this interface, the interface only contains a simple method:
>> 
>>     /**
>>      * @param output the output when this executable is running
>>      */
>>     void execute(PrintWriter output);
>> 
>> 
>> - Add two annotations (@Command and @Parameter) to describe the command meta info
>> 
>> - Use Factory API to register command, the following forms are supported
>> 
>> @Command(name = "My.Echo", description = "Echo description")
>> class Echo implements Executable {
>> 
>>     @Parameter(name = "text", ordinal=0, isMandatory = true)
>>     String text;
>> 
>>     @Parameter(name = "repeat", isMandatory = true, defaultValue = "1")
>>     int repeat;
>> 
>>     @Override
>>     public void execute(PrintWriter out) {
>>         for (int i = 0 ; i < repeat; i++) {
>>             out.println(text);
>>         }
>>     }
>> }
>> 
>> Factory.register(Echo.class);
>> 
>> 
>> 
>> Factory.register("My.Date", output -> {
>>     output.println(new Date());
>> });
>> 
>> 
>> - When the command is running, the VM will call `Executor.executeCommand` to execute the command. In the implementation of Executor, I introduced a simple timeout mechanism to prevent the command channel from being blocked.
>> 
>> At the VM layer, I extended the existing DCmd framework(implemented JavaDCmd and JavaDCmdFactoryImpl) to be compatible with existing functions (jmx, help, etc.).
>> 
>> In terms of security, considering that the SecurityManager will be deprecated, there are not too many considerations for the time being.
>> 
>> Any input is appreciated.
>> 
>> Thanks,
>> Denghui
>
> Denghui Dong has updated the pull request incrementally with one additional commit since the last revision:
> 
>   print argument key if not found

Seems no more comments on this issue, but I still think this is a useful feature and want it could be a standard feature.

The following is my thought.

The idea of ​​this feature originally came from our internal Java agent that detects the misusage of Unsafe API.

This agent can collect the call sites that allocate or free direct memory in the application(NMT could not do it IMO) to detect direct memory leaks.

In the beginning, it just prints call sites, without any statistical function, it's hard to use.

So we plan to use a way similar to jeprof (from jemalloc) to generate a report file that aggregates all useful information.

During the implementation process, we found that we need a mechanism to notify the agent to generate reports.
(Multiple unrelated dependent components in a Java application may require such a mechanism)

The common practice is:
a) Register a service port, triggered by an HTTP request
b) Triggered by signal
c) Generate reports periodically, or when the process exits

But these three ways have certain problems.
For a) we need to introduce a network component, will increase the complexity of implementation
For b) we cannot pass parameters
For c) some files that may never be used will be generated

Essentially, this question is how to notify the application to do a certain task, or in other words, how do we issue a command to the application.

Naturally, we think that `jcmd` can already issue some commands registered in VM to the application, why can't we extend to the java layer?

This feature will be very useful for some lightweight tools, just like the scenario we encountered, to notify the tools to perform certain operations.

In addition, this feature will also bring benefits to Java beginners.
For example, at the beginning, beginners may not use advanced log components, but they will also encounter the need to output debug logs. They may write code like this:


if (debug) {
  System.out.println("...");
}



If developers can easily and dynamically control the value of `debug`, it's attractive.


Factory.register("MyApp.flipDebug", out -> debug = !debug);

jcmd <pid> MyApp.flipDebug


I agree with what Erik said, we need to find applicable scenarios in some mainstream frameworks. After my preliminary investigation, I think we can apply this feature in the features of `health checks`, `graceful shutdown`, and `dynamic configuration updates`.

But to be honest, these frameworks are very mature and stable, and for compatibility purposes, it's hard to let them use this extension.

In terms of code maintainability, the implementation of this extension does not need to destroy the existing framework. The current implementation only extends the DCmd framework and provides several simple APIs for users to use. I think there will not be too many costs after it's stable.

If this feature could become a standard feature, I will be the first user:)

Best,
Denghui

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

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


More information about the hotspot-runtime-dev mailing list