Request for Review (XXL): 7104647: Adding a diagnostic command framework

Frederic Parain frederic.parain at oracle.com
Tue Dec 13 06:05:54 PST 2011


Hi Serguei,

Thanks for the review.
I've applied the changes and the new webrev is here:
http://cr.openjdk.java.net/~fparain/7104647/webrev.hotspot.05/

Regards,

Fred

On 12/13/11 10:43 AM, serguei.spitsyn at oracle.com wrote:
> Hi Frederik,
>
> Your fix is already in a good shape!
>
> src/share/vm/services/management.cpp:
>
>    It is better to have different diagnostic messages at lines 2181 and 2186
>    so that it is easy to find out what of the two lines caused an exception.
>    The messages would be better to be more specific.
>    The same applies to the lines 2221 and 2226.
>    Indent must be aligned with the first argument above.
>
> 2178   oop cmd = JNIHandles::resolve_external_guard(command);
> 2179   if (cmd == NULL) {
> 2180     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
> 2181                "Command line cannot be null.");
> 2182   }
> 2183   char* cmd_name = java_lang_String::as_utf8_string(cmd);
> 2184   if (cmd_name == NULL) {
> 2185     THROW_MSG(vmSymbols::java_lang_NullPointerException(),
> 2186                "Command line cannot be null.");
> 2187   }
> ...
> 2219   if (cmd == NULL) {
> 2220     THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
> 2221                "Command line cannot be null.");
> 2222   }
> 2223   char* cmdline = java_lang_String::as_utf8_string(cmd);
> 2224   if (cmdline == NULL) {
>
> 2225     THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
> 2226                "Command line cannot be null.");
> 2227   }
>
> The lines 2189 and 2194 look redundant:
>
> src/share/vm/services/diagnosticFramework.cpp:
>
> 2188   DCmd* dcmd = NULL;
> 2189   {
> 2190     DCmdFactory*factory = DCmdFactory::factory(cmd_name, strlen(cmd_name));
> 2191     if (factory != NULL) {
> 2192       dcmd = factory->create_resource_instance(NULL);
> 2193     }
> 2194   }
>
> Indent is not correct at the lines 2205-2211:
>
> 2204   for (int i = 0; i<  array->length(); i++) {
> 2205       infoArray[i].name = array->at(i)->name();
> 2206       infoArray[i].description = array->at(i)->description();
> 2207       infoArray[i].type = array->at(i)->type();
> 2208       infoArray[i].default_string = array->at(i)->default_string();
> 2209       infoArray[i].mandatory = array->at(i)->is_mandatory();
> 2210       infoArray[i].option = array->at(i)->is_option();
> 2211       infoArray[i].position = array->at(i)->position();
> 2212   }
>
>
>     Space is missed after 'while':
>
>     320   while(arg != NULL) {
>     326   while(arg != NULL) {
>
>
> Thanks,
> Serguei
>
>
>
> On 12/12/11 7:56 AM, Frederic Parain wrote:
>> Minor updates:
>> http://cr.openjdk.java.net/~fparain/7104647/webrev.hotspot.04/
>>
>> Fred
>>
>> On 12/12/11 03:29 PM, Frederic Parain wrote:
>>> Hi Paul,
>>>
>>> Thank you for the review.
>>> I've applied all your recommendations except the refactoring
>>> in diagnosticCommandFramework.cpp (too few lines can be really
>>> factored out without passing many arguments).
>>>
>>> New webrev is here:
>>> http://cr.openjdk.java.net/~fparain/7104647/webrev.hotspot.03/
>>>
>>> Regards,
>>>
>>> Fred
>>>
>>> On 12/ 8/11 07:26 PM, Paul Hohensee wrote:
>>>> For the hotspot part at
>>>> http://cr.openjdk.java.net/~fparain/7104647/webrev.hotspot.00/
>>>>
>>>> Most of my comments are style-related. Nice job on the implementation
>>>> architecture.
>>>>
>>>> In attachListener.cpp:
>>>>
>>>> You might want to delete the first "return JNI_OK;" line, since the
>>>> code
>>>> under
>>>> HAS_PENDING_EXCEPTION just falls through.
>>>>
>>>> In jmm.h:
>>>>
>>>> Be nice to indent "(JNIEnv" on lines 318, 319 and 325 the same as the
>>>> existing declarations. Add a newline just before it on line 322.
>>>>
>>>>
>>>> In diagnosticFramework.hpp:
>>>>
>>>> Fix indenting for lines 63-66, insert blank before "size_t" on line 48.
>>>>
>>>> Hotspot convention is that getter method names don't include a "get_"
>>>> prefix.
>>>> So, e.g., DCmdArgIter::get_key_addr() s/b DCmdArgIter::key_addr().
>>>> Similarly, getters such as is_enabled() should retrieve a field named
>>>> "_is_enabled"
>>>> rather than one named "enabled". You follow the "_is_enabled"
>>>> convention
>>>> in other places such as GenDCmdArgument. Or you could use enabled() to
>>>> get the value of the _enabled field.
>>>>
>>>> Also generally, I'd use accessor methods in the implementation of more
>>>> complex member methods rather than access the underlying fields
>>>> directly.
>>>> E.g. in GenDCmdArgument::read_value, I'd use is_set() and
>>>> set_is_set(true),
>>>> (set_is_set() is not actually defined, but should be) rather than
>>>> directly
>>>> accessing _is_set. Though sometimes doing this is too much of a pain
>>>> with fields whose type is a template argument, as in the
>>>> DCmdArggument<char*>::parse_value() method in diagnosticArgument.cpp.
>>>>
>>>> For easy readability, it'd be nice to line up field names (the ones
>>>> with an
>>>> _ prefix) at the same column.
>>>>
>>>> On line 200, "instanciated" -> "instantiated"
>>>>
>>>> On line 218, I'd use "heap_allocated" rather than "heap" for the formal
>>>> arg name.
>>>>
>>>> On line 248, you could indent the text to start underneath
>>>> "outputStream".
>>>> I generally find that indenting arguments lines (formal or actual) so
>>>> they line
>>>> up with the first argument position make the code more readable, but
>>>> I'm
>>>> not
>>>> religious about it.
>>>>
>>>> On line 265, "instanciated" -> "instantiated"
>>>>
>>>> DCmdFactorys are members of a singly-linked list, right? If so, it'd be
>>>> good to
>>>> have a comment to that effect on the declaration of _next.
>>>>
>>>> On line 322, insert a blank before "true". You might fix this in other
>>>> places
>>>> where there's no blank between a comma in an argument list and the
>>>> following parameter value.
>>>>
>>>>
>>>> In diagnosticCommandFramework.cpp:
>>>>
>>>> The code from lines 80-95 and 105-120 is identical. Factor out?
>>>>
>>>>
>>>> In diagnosticArgument.cpp:
>>>>
>>>> On line 41, insert blanks before the actual arguments. (see above
>>>> generic comment)
>>>>
>>>> On line 77, the "if" is indented one space too many.
>>>>
>>>>
>>>> In management.cpp:
>>>>
>>>> I'd be consistent with having or not having a space between "while",
>>>> "if" and "for"
>>>> and the following "(" in this and your other code. Most hotspot code
>>>> has
>>>> a space.
>>>>
>>>>
>>>> Thanks,
>>>>
>>>> Paul
>>>>
>>>>
>>>> On 12/2/11 8:57 AM, Frederic Parain wrote:
>>>>> Hi All,
>>>>>
>>>>> [Posting to serviceability-dev, runtime-dev and core-libs-dev
>>>>> because changes are pretty big and touch all these areas]
>>>>>
>>>>> Here's a framework for issuing diagnostics commands to the JVM.
>>>>> Diagnostic commands are actions executed inside the JVM mainly
>>>>> for monitoring or management purpose. This work has two parts.
>>>>> The first part is in the hotspot repository and contains the
>>>>> framework itself with two diagnostic commands. The second
>>>>> part is in the JDK repository and contains the command line
>>>>> utility to invoke diagnostic commands as well as the
>>>>> HotSpotDiagnosticMXBean extensions. The HotSpotDiagnosticMXBean
>>>>> extensions allow a remote client to discover and invoke
>>>>> diagnostic commands using a JMX connection.
>>>>>
>>>>> This changeset only contains two diagnostic commands, more
>>>>> commands will be added in the future, as a standalone effort
>>>>> to improve the monitoring and management services of the
>>>>> JVM, or as part of other projects.
>>>>>
>>>>> Webrevs are here:
>>>>> http://cr.openjdk.java.net/~fparain/7104647/webrev.hotspot.00/
>>>>> http://cr.openjdk.java.net/~fparain/7104647/webrev.jdk.00/
>>>>>
>>>>> Here's a technical description of this work:
>>>>>
>>>>> 1 - The Diagnostic Command Framework
>>>>> 1-1 Overview
>>>>>
>>>>> The diagnostic command framework is fully implemented in native code
>>>>> and relies on the HotSpot's internal exception mechanism.
>>>>> The rational of a pure native implementation is to be able to execute
>>>>> diagnostic commands even in critical situations like an OutOfMemory
>>>>> error. All diagnostic commands are registered in a single list, and
>>>>> two
>>>>> flags control the way a user can interact with them. The "hidden" flag
>>>>> prevents a diagnostic command from appearing in the list of available
>>>>> commands returned by the "help" command. However, it's still
>>>>> possible to
>>>>> get the detailed help message for a hidden command with the "help
>>>>> <command name>" syntax (but it requires to know the name of the hidden
>>>>> command). The second flag is "enabled" and it controls if a command
>>>>> can
>>>>> be invoked or not. When listed with the "help" commands, disabled
>>>>> commands appear with a "[disabled]" label in their description. If the
>>>>> user tries to invoke a disabled command, an error message is returned
>>>>> and the command is not run. This error message can be customized on a
>>>>> per command base. The framework just provides these two flags with
>>>>> their
>>>>> semantic, it doesn't provide any policy or mechanism to set or modify
>>>>> these flags. These actions will be delegated to the JVM or special
>>>>> diagnostic commands.
>>>>>
>>>>> 1-2 Implementation
>>>>>
>>>>> All diagnostic commands are implemented as subclasses of the DCmd
>>>>> class
>>>>> defined in services/diagnosticFramework.hpp. Here's the layout of the
>>>>> DCmd class and the list of methods that a new command has to define or
>>>>> overwrite:
>>>>>
>>>>> class DCmd {
>>>>> DCmd(outputStream *output);
>>>>>
>>>>> static const char *get_name();
>>>>>
>>>>> static const char *get_description();
>>>>>
>>>>> static const char *get_disabled_message();
>>>>>
>>>>> static const char *get_impact();
>>>>>
>>>>> static int get_num_arguments();
>>>>>
>>>>> virtual void print_help(outputStream* out);
>>>>>
>>>>> virtual void parse(CmdLine* line, char delim, TRAPS);
>>>>>
>>>>> virtual void execute(TRAPS);
>>>>>
>>>>> virtual void reset(TRAPS);
>>>>>
>>>>> virtual void cleanup();
>>>>>
>>>>> virtual GrowableArray<const char *>* get_argument_name_array();
>>>>>
>>>>> virtual GrowableArray<DCmdArgumentInfo*>* get_argument_info_array();
>>>>> }
>>>>>
>>>>> A diagnostic command is always instantiated with an outputStream in
>>>>> parameter. This outputStream can point either to a file, a buffer or a
>>>>> socket (see the ostream.hpp file).
>>>>>
>>>>> The get_name() method returns the string that will identify the
>>>>> command
>>>>> (i.e. the string to put on the command line to invoke it).
>>>>>
>>>>> The get_description() methods returns the global description of the
>>>>> command.
>>>>>
>>>>> The get_disabled_message() returns the customized message to return
>>>>> when
>>>>> the command is disabled, without having to instantiate the command.
>>>>>
>>>>> The get_impact() returns a description of the intrusiveness of the
>>>>> diagnostic command on the Java Virtual Machine behavior. The rational
>>>>> for this method is that some diagnostic commands can seriously disrupt
>>>>> the behavior of the Java Virtual Machine (for instance a Thread
>>>>> Dump for
>>>>> an application with several tens of thousands of threads, or a Head
>>>>> Dump
>>>>> with a 40GB+ heap size) and other diagnostic commands have no serious
>>>>> impact on the JVM (for instance, getting the command line arguments or
>>>>> the JVM version). The recommended format for the description is
>>>>> <impact
>>>>> level>: [longer description], where the impact level is selected among
>>>>> this list: {low, medium, high}. The optional longer description can
>>>>> provide more specific details like the fact that Thread Dump impact
>>>>> depends on the heap size.
>>>>>
>>>>> The get_num_arguments() returns the number of options/arguments
>>>>> recognized by the diagnostic command. This method is only used by the
>>>>> JMX interface support (see below).
>>>>>
>>>>> The print_help() methods prints a detailed help on the outputStream
>>>>> passed in argument. The detailed help contains the list of all
>>>>> supported
>>>>> options with their type and description.
>>>>>
>>>>> The parse() method is in charge of parsing the command arguments. Each
>>>>> command is free to implement its own argument parser. However, an
>>>>> argument parser framework is provided (see section 1-3) to ease the
>>>>> implementation, but its use is optional. The parse method takes a
>>>>> delimiter character in argument, which is used to mark the limit
>>>>> between
>>>>> two arguments (typically invocation from jcmd will use a space
>>>>> character
>>>>> as a delimiter while invocation from the JVM command line parsing code
>>>>> will use a comma as a delimiter).
>>>>>
>>>>> The execute() method is naturally the one to invoke to get the
>>>>> diagnostic command executed. The parse() and the execute() methods are
>>>>> dissociated, so it's a possible perform the argument parsing in one
>>>>> thread, and delegate the execution to another thread, as long as the
>>>>> diagnostic command doesn't reference thread local variables. The
>>>>> framework allows several instances of the same diagnostic command
>>>>> to be
>>>>> executed in parallel. If for some reasons concurrent executions should
>>>>> not be allowed for a given diagnostic command, this is the
>>>>> responsibility of the diagnostic command implementor to enforce this
>>>>> rule, for instance by protecting the body of the execute() method
>>>>> with a
>>>>> global lock.
>>>>>
>>>>> The reset() method is used to initialize the internal fields of the
>>>>> diagnostic command or to reset the internal fields to their initial
>>>>> value to be able to re-use an already allocated diagnostic command
>>>>> instance.
>>>>>
>>>>> The cleanup() method is used to perform perform cleanup (like
>>>>> freeing of
>>>>> all memory allocated to store internal data). The DCmd extends the
>>>>> ResourceObj class, so when allocated in a ResourceArea, destructors
>>>>> cannot be used to perform cleanup. To ensure that cleanup is performed
>>>>> in all cases, it is recommended to create a DCmdMark instance for each
>>>>> DCmd instance. DCmdMark is a stack allocated object with a pointer
>>>>> to a
>>>>> DCmd instance. When the DCmdMark is destroyed, its destructor calls
>>>>> the
>>>>> cleanup() method of the DCmd instance it points to. If the DCmd
>>>>> instance
>>>>> has been allocated on the C-Heap, the DCmdMark will also free the
>>>>> memory
>>>>> allocated to store the DCmd instance.
>>>>>
>>>>> The get_argument_name_array() and get_argument_info_array() are
>>>>> related
>>>>> to the JMX interface of the diagnostic command framework, so they are
>>>>> described in section 3.
>>>>>
>>>>> 1-3 DCmdParser framework
>>>>>
>>>>> The DCmdParser class is an optional framework to help development of
>>>>> argument parsers. It provides many features required by the diagnostic
>>>>> command framework (generation of the help message or the argument
>>>>> descriptions for the JMX interface) but all these features can
>>>>> easily be
>>>>> re-implemented if a developer decides not to use the DCmdParser
>>>>> framework.
>>>>>
>>>>> The DCmdParser class is relying on the DCmdArgument template. This
>>>>> template must be used to define the different types of argument the
>>>>> parser will have to handle. When a new specialization of the
>>>>> template is
>>>>> done, three methods have to be provided:
>>>>>
>>>>> void parse_value(const char *str,size_t len,TRAPS);
>>>>> void init_value(TRAPS);
>>>>> void destroy_value();
>>>>>
>>>>> The parse_value() method is used to convert a string into an argument
>>>>> value. The print_value() method is used to display the default value
>>>>> (support for the detailed help message). The init_value() method is
>>>>> used
>>>>> to initialize or reset the argument value. The destroy_value()
>>>>> method is
>>>>> a clean-up method (useful when the argument has allocated some C-Heap
>>>>> memory to store its value and this memory has to be freed before
>>>>> destroying the DCmdArgument instance).
>>>>>
>>>>> The DCmdParser makes a distinction between options and arguments.
>>>>> Options are identified by a key name that must appear on the command
>>>>> line, while argument are identified just by the position of the
>>>>> argument
>>>>> on the command line. Options use the <key>=<value> syntax. In case of
>>>>> boolean options, the '=<value>' part of the syntax can be omitted
>>>>> to set
>>>>> the option to true. Arguments are just sequences characters
>>>>> delimited by
>>>>> a separator character. This separator can be specified at runtime when
>>>>> invoking the diagnostic command framework. If an argument contain a
>>>>> character that could be used as a delimiter, it's possible to enclose
>>>>> the argument between single or double quotes. Options are arguments
>>>>> are
>>>>> instantiated using the same DCmdArgument class but they're registered
>>>>> differently to the DCmdParser.
>>>>>
>>>>> The way to use the DCmdParser is to declare the parser and the
>>>>> option/arguments as fields of the diagnostic command class (which is
>>>>> itself a sub-class of the DCmd class), like this:
>>>>>
>>>>>
>>>>> class EchoDCmd : public DCmd {
>>>>> protected:
>>>>> DCmdParser _dcmdparser;
>>>>>
>>>>> DCmdArgument<jlong> _required;
>>>>>
>>>>> DCmdArgument<jlong> _intval;
>>>>>
>>>>> DCmdArgument<bool> _boolval;
>>>>>
>>>>> DCmdArgument<char *> _stringval;
>>>>>
>>>>> DCmdArgument<char *> _first_arg;
>>>>>
>>>>> DCmdArgument<jlong> _second_arg;
>>>>>
>>>>> DCmdArgument<char *> _optional_arg;
>>>>>
>>>>> }
>>>>>
>>>>> The parser and the options/arguments must be initialized before the
>>>>> diagnostic command class, and the options/arguments have to be
>>>>> registered to the parser like this:
>>>>>
>>>>> EchoDCmd(outputStream *output) : DCmd(output),
>>>>> _stringval("-strval","a string argument","STRING",false),
>>>>>
>>>>> _boolval("-boolval","a boolean argument","BOOLEAN",false),
>>>>>
>>>>> _intval("-intval","an integer argument","INTEGER",false),
>>>>>
>>>>> _required("-req","a mandatory integer argument","INTEGER",true),
>>>>>
>>>>> _fist_arg("first argument","a string argument","STRING",true),
>>>>>
>>>>> _second_arg("second argument,"an integer argument,"INTEGER",true),
>>>>>
>>>>> _optional_arg("optional argument","an optional string
>>>>> argument","STRING","false")
>>>>>
>>>>> {
>>>>>
>>>>> _dcmdparser.add_dcmd_option(&_stringval)
>>>>>
>>>>> _dcmdparser.add_dcmd_option(&_boolval);
>>>>>
>>>>> _dcmdparser.add_dcmd_option(&_intval);
>>>>>
>>>>> _dcmdparser.add_dcmd_option(&_required);
>>>>>
>>>>> _dcmdparser.add_argument(&_first_arg);
>>>>>
>>>>> _dcmdparser.add_argument(&_second_arg);
>>>>>
>>>>> _dcmdparser.add_argument(&_optional_arg);
>>>>> };
>>>>>
>>>>> The add_dcmd_argument()/ add_dcmd_option() method is used to add an
>>>>> argument/option to the parser. The option/argument constructor
>>>>> takes the
>>>>> name of the option/argument, its description, a string describing its
>>>>> type and a boolean to specify if the option/argument is mandatory or
>>>>> not. The parser doesn't support option/argument duplicates (having the
>>>>> same name) but the code currently doesn't check for duplicates.The
>>>>> order
>>>>> used to register options has no impact on the parser. However, the
>>>>> order
>>>>> used to register arguments is critical because the parser will use the
>>>>> same order to parse the command line. In the example above, the parser
>>>>> expects to have a first argument of type STRING (parsed using
>>>>> _first_arg), then a second argument of type INTEGER (parsed using
>>>>> _second_arg) and optionally a third parameter of type STRING (parsed
>>>>> using _optional_arg). A mandatory option or argument has to be specify
>>>>> every time the command is invoked. If it is missing, an exception is
>>>>> thrown at the end of the parsing. Optional arguments have to be
>>>>> registered after mandatory arguments. An optional argument will be
>>>>> considered for parsing only if all arguments before it (mandatory or
>>>>> not) have already been used to parse the command line.
>>>>>
>>>>> The DCmdParser and its DCmdArgument instances are embedded in the DCmd
>>>>> instance. The rational for this design is to limit the number of
>>>>> C-heap
>>>>> allocations but also to be able to pre-allocate diagnostic command
>>>>> instances for critical situations. If the process is running out of
>>>>> C-heap space, it's not possible to instantiate new diagnostic commands
>>>>> to troubleshoot the situation. By pre-allocating some diagnostic
>>>>> commands, it will be possible to run them even in this critical
>>>>> situation. Of course, the diagnostic command itself should not try to
>>>>> allocate memory during its execution, this prevents the diagnostic
>>>>> command to use variable length arguments like strings. By nature,
>>>>> pre-allocated diagnostic commands aim to be re-usable, this is the
>>>>> purpose of the reset() method which restores the default status of all
>>>>> arguments.
>>>>>
>>>>> 1-4 Internal invocation
>>>>>
>>>>> Using a diagnostic command from the JVM itself is pretty easy:
>>>>> instantiate the class and invoke the parse() method then the execute()
>>>>> method. A diagnostic command can be instantiated from inside the JVM
>>>>> even it is not registered. This is a difference with the external
>>>>> invocations (from jcmd or JMX) that require the command to be
>>>>> registered.
>>>>>
>>>>> 2 - The JCmd interface
>>>>>
>>>>> Diagnostic commands can also be invoked from outside the JVM process,
>>>>> using the new 'jcmd' utility. The jcmd program uses the attach API
>>>>> to connect to the JVM, send requests and receive results. The
>>>>> jcmd utility must be launched on the same machine than the one running
>>>>> the JVM (its a local tool). Launched without arguments, jcmd
>>>>> displays a
>>>>> list of all JVMs running on the machine. The jcmd source code is in
>>>>> the jdk repository like other existing j* tools.
>>>>>
>>>>> To execute a diagnostic command in a particular JVM, the generic
>>>>> syntax is:
>>>>>
>>>>> jcmd <pid_of_the_jvm> <command_name> [arguments]
>>>>>
>>>>> The attachListener has been modified to recognized the jcmd requests.
>>>>> When a jcmd request is identified, it is parsed to extract the command
>>>>> name. The JVM performs a look up of this command in a list of
>>>>> registered
>>>>> commands. To be executable by an external request, a diagnostic
>>>>> command
>>>>> has to be registered. The registration is performed with the
>>>>> DCmdFactory
>>>>> class (see services/management.cpp).
>>>>>
>>>>> 3 - The JMX interface
>>>>>
>>>>> The framework provides a JMX based interface to the diagnostic
>>>>> commands.
>>>>> This interface allows remote invocation of diagnostic commands
>>>>> through a
>>>>> JMX connection.
>>>>>
>>>>> 3-1 The interface
>>>>>
>>>>> The information related to the diagnostic commands are accessible
>>>>> through new methods added to the
>>>>> com.sun.management.HotspotDiagnosticMXBean:
>>>>>
>>>>> public List<String> getDiagnosticCommands();
>>>>>
>>>>> public DiagnosticCommandInfo getDiagnosticCommandInfo(String command);
>>>>>
>>>>> public List<DiagnosticCommandInfo>
>>>>> getDiagnosticCommandInfo(List<String>
>>>>> command);
>>>>>
>>>>> public List<DiagnosticCommandInfo> getDiagnosticCommandInfo();
>>>>>
>>>>> public String execute(String commandLine) throws
>>>>> IllegalArgumentException ;
>>>>>
>>>>> public String execute(String cmd, String... arguments)
>>>>> throws IllegalArgumentException;
>>>>>
>>>>>
>>>>> The getDiagnosticCommands() method returns an array containing the
>>>>> names
>>>>> of the not-hidden registered diagnostic commands.
>>>>>
>>>>> The three getDiagnosticCommandInfo() methods return one or several
>>>>> diagnostic command descriptions using the DiagnosticCommandInfo class.
>>>>>
>>>>> The two execute() methods allow the user the invoke a diagnostic
>>>>> command
>>>>> in different ways.
>>>>>
>>>>> The DiagnosticCommandInfo class is describing a diagnostic command
>>>>> with
>>>>> the following information:
>>>>>
>>>>> public class DiagnosticCommandInfo {
>>>>>
>>>>> public String getName();
>>>>>
>>>>> public String getDescription();
>>>>>
>>>>> public String getImpact();
>>>>>
>>>>> public boolean isEnabled();
>>>>>
>>>>> public List<DiagnosticCommandArgumentInfo> getArgumentsInfo();
>>>>> }
>>>>>
>>>>> The getName() method returns the name of the diagnostic command. This
>>>>> name is the one to use in execute() methods to invoke the diagnostic
>>>>> command.
>>>>>
>>>>> The getDescription() method returns a general description of the
>>>>> diagnostic command.
>>>>>
>>>>> The getImpact() method returns a description of the intrusiveness of
>>>>> diagnostic command.
>>>>>
>>>>> The isEnabled() method returns true if the method is enabled, false if
>>>>> it is disabled. A disabled method cannot be executed.
>>>>>
>>>>> The getArgumentsInfo() returns a list of descriptions for the
>>>>> options or
>>>>> arguments recognized by the diagnostic command. Each
>>>>> option/argument is
>>>>> described by a DiagnosticCommandArgumentInfo instance:
>>>>>
>>>>> public class DiagnosticCommandArgumentInfo {
>>>>>
>>>>> public String getName();
>>>>>
>>>>> public String getDescription();
>>>>>
>>>>> public String getType();
>>>>>
>>>>> public String getDefault();
>>>>>
>>>>> public boolean isMandatory();
>>>>>
>>>>> public boolean isOption();
>>>>>
>>>>> public int getPosition();
>>>>> }
>>>>>
>>>>> If the DiagnosticCommandArgumentInfo instance describes an option,
>>>>> isOption() returns true and getPosition() returns -1. Otherwise, when
>>>>> the DiagnosticCommandArgumentInfo instance describes an argument,
>>>>> isOption() returns false and getPosition() returns the expected
>>>>> position
>>>>> for this argument. The position of an argument is defined
>>>>> relatively to
>>>>> all arguments passed on the command line, options are not considered
>>>>> when defining an argument position. The getDefault() method returns
>>>>> the
>>>>> default value of the argument if a default has been defined, otherwise
>>>>> it returns null.
>>>>>
>>>>> 3-2 The implementation
>>>>>
>>>>> The framework has been designed in a way that prevents diagnostic
>>>>> command developers to worry about the JMX interface. In addition to
>>>>> the methods described in section 1-2, a diagnostic command
>>>>> developer has
>>>>> to provide three methods:
>>>>>
>>>>> int get_num_arguments()
>>>>>
>>>>> which returns the number of option and arguments supported by the
>>>>> command.
>>>>>
>>>>> GrowableArray<const char *>* get_argument_name_array()
>>>>>
>>>>> which provides the name of the arguments supported by the command.
>>>>>
>>>>> GrowableyArray<DCmdArgumentInfo*>* get_argument_info_array()
>>>>>
>>>>> which provides the description of each argument with a
>>>>> DCmdArgumentInfo
>>>>> instance. DCmdArgumentInfo is a C++ class used by the framework to
>>>>> generate the sun.com.management.DcmdArgumentInfo instances. This is
>>>>> done
>>>>> automatically and the diagnostic command developer doesn't need to
>>>>> know
>>>>> how to create Java objects from the runtime.
>>>>>
>>>>> 4 - The Diagnostic Commands
>>>>>
>>>>> To avoid name collisions between diagnostic commands coming from
>>>>> different projects, use of a flat name space should be avoided and
>>>>> a more structured organization is recommended. The framework itself
>>>>> doesn't depend on this organization, so it will be a set of rules
>>>>> defining a convention in the way commands are named.
>>>>>
>>>>> Diagnostic commands can easily organized in a hierarchical way, so the
>>>>> template for a command name can be:
>>>>>
>>>>> <domain>.[sub-domain.]<command>
>>>>>
>>>>> This template can be extended with sub-sub-domains and so on.
>>>>>
>>>>> A special set of commands without domain will be reserved for the
>>>>> commands related to the diagnostic framework itself, like the "help"
>>>>> command.
>>>>>
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Fred
>>>>>
>>>
>>
>

-- 
Frederic Parain - Oracle
Grenoble Engineering Center - France
Phone: +33 4 76 18 81 17
Email: Frederic.Parain at Oracle.com



More information about the serviceability-dev mailing list