/* * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP #define SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP #include "classfile/vmSymbols.hpp" #include "memory/allocation.hpp" #include "runtime/arguments.hpp" #include "runtime/os.hpp" #include "runtime/vmThread.hpp" #include "utilities/ostream.hpp" enum DCmdSource { DCmd_Source_Internal = 0x01U, // invocation from the JVM DCmd_Source_AttachAPI = 0x02U, // invocation via the attachAPI DCmd_Source_MBean = 0x04U // invocation via a MBean }; // Warning: strings referenced by the JavaPermission struct are passed to // the native part of the JDK. Avoid use of dynamically allocated strings // that could be de-allocated before the JDK native code had time to // convert them into Java Strings. struct JavaPermission { const char* _class; const char* _name; const char* _action; }; // CmdLine is the class used to handle a command line containing a single // diagnostic command and its arguments. It provides methods to access the // command name and the beginning of the arguments. The class is also // able to identify commented command lines and the "stop" keyword class CmdLine : public StackObj { private: const char* _cmd; size_t _cmd_len; const char* _args; size_t _args_len; public: CmdLine(const char* line, size_t len, bool no_command_name); const char* args_addr() const { return _args; } size_t args_len() const { return _args_len; } const char* cmd_addr() const { return _cmd; } size_t cmd_len() const { return _cmd_len; } bool is_empty() const { return _cmd_len == 0; } bool is_executable() const { return is_empty() || _cmd[0] != '#'; } bool is_stop() const { return !is_empty() && strncmp("stop", _cmd, _cmd_len) == 0; } }; // Iterator class taking a character string in input and returning a CmdLine // instance for each command line. The argument delimiter has to be specified. class DCmdIter : public StackObj { friend class DCmd; private: const char* const _str; const char _delim; const size_t _len; size_t _cursor; public: DCmdIter(const char* str, char delim) : _str(str), _delim(delim), _len(::strlen(str)), _cursor(0) {} bool has_next() const { return _cursor < _len; } CmdLine next() { assert(_cursor <= _len, "Cannot iterate more"); size_t n = _cursor; while (n < _len && _str[n] != _delim) n++; CmdLine line(&(_str[_cursor]), n - _cursor, false); _cursor = n + 1; // The default copy constructor of CmdLine is used to return a CmdLine // instance to the caller. return line; } }; // Iterator class to iterate over diagnostic command arguments class DCmdArgIter : public ResourceObj { const char* const _buffer; const size_t _len; size_t _cursor; const char* _key_addr; size_t _key_len; const char* _value_addr; size_t _value_len; const char _delim; public: DCmdArgIter(const char* buf, size_t len, char delim) : _buffer(buf), _len(len), _cursor(0), _key_addr(NULL), _key_len(0), _value_addr(NULL), _value_len(0), _delim(delim) {} bool next(TRAPS); const char* key_addr() const { return _key_addr; } size_t key_length() const { return _key_len; } const char* value_addr() const { return _value_addr; } size_t value_length() const { return _value_len; } }; // A DCmdInfo instance provides a description of a diagnostic command. It is // used to export the description to the JMX interface of the framework. class DCmdInfo : public ResourceObj { protected: const char* const _name; /* Name of the diagnostic command */ const char* const _description; /* Short description */ const char* const _impact; /* Impact on the JVM */ const JavaPermission _permission; /* Java Permission required to execute this command if any */ const int _num_arguments; /* Number of supported options or arguments */ const bool _is_enabled; /* True if the diagnostic command can be invoked, false otherwise */ public: DCmdInfo(const char* name, const char* description, const char* impact, JavaPermission permission, int num_arguments, bool enabled) : _name(name), _description(description), _impact(impact), _permission(permission), _num_arguments(num_arguments), _is_enabled(enabled) {} const char* name() const { return _name; } const char* description() const { return _description; } const char* impact() const { return _impact; } const JavaPermission& permission() const { return _permission; } int num_arguments() const { return _num_arguments; } bool is_enabled() const { return _is_enabled; } static bool by_name(void* name, DCmdInfo* info); }; // A DCmdArgumentInfo instance provides a description of a diagnostic command // argument. It is used to export the description to the JMX interface of the // framework. class DCmdArgumentInfo : public ResourceObj { protected: const char* const _name; /* Option/Argument name*/ const char* const _description; /* Short description */ const char* const _type; /* Type: STRING, BOOLEAN, etc. */ const char* const _default_string; /* Default value in a parsable string */ const bool _mandatory; /* True if the option/argument is mandatory */ const bool _option; /* True if it is an option, false if it is an argument */ /* (see diagnosticFramework.hpp for option/argument definitions) */ const bool _multiple; /* True is the option can be specified several time */ const int _position; /* Expected position for this argument (this field is */ /* meaningless for options) */ public: DCmdArgumentInfo(const char* name, const char* description, const char* type, const char* default_string, bool mandatory, bool option, bool multiple, int position = -1) : _name(name), _description(description), _type(type), _default_string(default_string), _mandatory(mandatory), _option(option), _multiple(multiple), _position(position) {} const char* name() const { return _name; } const char* description() const { return _description; } const char* type() const { return _type; } const char* default_string() const { return _default_string; } bool is_mandatory() const { return _mandatory; } bool is_option() const { return _option; } bool is_multiple() const { return _multiple; } int position() const { return _position; } }; // The DCmdParser class can be used to create an argument parser for a // diagnostic command. It is not mandatory to use it to parse arguments. // The DCmdParser parses a CmdLine instance according to the parameters that // have been declared by its associated diagnostic command. A parameter can // either be an option or an argument. Options are identified by the option name // while arguments are identified by their position in the command line. The // position of an argument is defined relative to all arguments passed on the // command line, options are not considered when defining an argument position. // The generic syntax of a diagnostic command is: // // [