Path: blob/master/src/hotspot/share/services/diagnosticCommand.cpp
64440 views
/*1* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "jvm.h"26#include "classfile/classLoaderHierarchyDCmd.hpp"27#include "classfile/classLoaderStats.hpp"28#include "classfile/javaClasses.hpp"29#include "classfile/systemDictionary.hpp"30#include "classfile/vmClasses.hpp"31#include "code/codeCache.hpp"32#include "compiler/compileBroker.hpp"33#include "compiler/directivesParser.hpp"34#include "gc/shared/gcVMOperations.hpp"35#include "memory/metaspace/metaspaceDCmd.hpp"36#include "memory/resourceArea.hpp"37#include "memory/universe.hpp"38#include "oops/objArrayOop.inline.hpp"39#include "oops/oop.inline.hpp"40#include "oops/typeArrayOop.inline.hpp"41#include "runtime/fieldDescriptor.inline.hpp"42#include "runtime/flags/jvmFlag.hpp"43#include "runtime/handles.inline.hpp"44#include "runtime/interfaceSupport.inline.hpp"45#include "runtime/javaCalls.hpp"46#include "runtime/jniHandles.hpp"47#include "runtime/os.hpp"48#include "runtime/vmOperations.hpp"49#include "runtime/vm_version.hpp"50#include "services/diagnosticArgument.hpp"51#include "services/diagnosticCommand.hpp"52#include "services/diagnosticFramework.hpp"53#include "services/heapDumper.hpp"54#include "services/management.hpp"55#include "services/writeableFlags.hpp"56#include "utilities/debug.hpp"57#include "utilities/events.hpp"58#include "utilities/formatBuffer.hpp"59#include "utilities/macros.hpp"60#ifdef LINUX61#include "trimCHeapDCmd.hpp"62#endif6364static void loadAgentModule(TRAPS) {65ResourceMark rm(THREAD);66HandleMark hm(THREAD);6768JavaValue result(T_OBJECT);69Handle h_module_name = java_lang_String::create_from_str("jdk.management.agent", CHECK);70JavaCalls::call_static(&result,71vmClasses::module_Modules_klass(),72vmSymbols::loadModule_name(),73vmSymbols::loadModule_signature(),74h_module_name,75THREAD);76}7778void DCmdRegistrant::register_dcmds(){79// Registration of the diagnostic commands80// First argument specifies which interfaces will export the command81// Second argument specifies if the command is enabled82// Third argument specifies if the command is hidden83uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI84| DCmd_Source_MBean;85DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(full_export, true, false));86DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(full_export, true, false));87DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(full_export, true, false));88DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(full_export, true, false));89DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(full_export, true, false));90DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SetVMFlagDCmd>(full_export, true, false));91DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMDynamicLibrariesDCmd>(full_export, true, false));92DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export, true, false));93DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMInfoDCmd>(full_export, true, false));94DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export, true, false));95DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export, true, false));96DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapInfoDCmd>(full_export, true, false));97DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<FinalizerInfoDCmd>(full_export, true, false));98#if INCLUDE_SERVICES99DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));100DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));101DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemDictionaryDCmd>(full_export, true, false));102DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export, true, false));103DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export, true, false));104DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<StringtableDCmd>(full_export, true, false));105DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<metaspace::MetaspaceDCmd>(full_export, true, false));106DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<EventLogDCmd>(full_export, true, false));107#if INCLUDE_JVMTI // Both JVMTI and SERVICES have to be enabled to have this dcmd108DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIAgentLoadDCmd>(full_export, true, false));109#endif // INCLUDE_JVMTI110#endif // INCLUDE_SERVICES111#if INCLUDE_JVMTI112DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIDataDumpDCmd>(full_export, true, false));113#endif // INCLUDE_JVMTI114DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));115DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));116DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderHierarchyDCmd>(full_export, true, false));117DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));118DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));119DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));120#ifdef LINUX121DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PerfMapDCmd>(full_export, true, false));122DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TrimCLibcHeapDCmd>(full_export, true, false));123#endif // LINUX124DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(full_export, true, false));125DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeHeapAnalyticsDCmd>(full_export, true, false));126127DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesPrintDCmd>(full_export, true, false));128DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesAddDCmd>(full_export, true, false));129DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesRemoveDCmd>(full_export, true, false));130DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesClearDCmd>(full_export, true, false));131132// Enhanced JMX Agent Support133// These commands won't be exported via the DiagnosticCommandMBean until an134// appropriate permission is created for them135uint32_t jmx_agent_export_flags = DCmd_Source_Internal | DCmd_Source_AttachAPI;136DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(jmx_agent_export_flags, true,false));137DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(jmx_agent_export_flags, true,false));138DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(jmx_agent_export_flags, true,false));139DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStatusDCmd>(jmx_agent_export_flags, true,false));140141// Debug on cmd (only makes sense with JVMTI since the agentlib needs it).142#if INCLUDE_JVMTI143DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DebugOnCmdStartDCmd>(full_export, true, true));144#endif // INCLUDE_JVMTI145146#if INCLUDE_CDS147DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DumpSharedArchiveDCmd>(full_export, true, false));148#endif // INCLUDE_CDS149}150151#ifndef HAVE_EXTRA_DCMD152void DCmdRegistrant::register_dcmds_ext(){153// Do nothing here154}155#endif156157158HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),159_all("-all", "Show help for all commands", "BOOLEAN", false, "false"),160_cmd("command name", "The name of the command for which we want help",161"STRING", false) {162_dcmdparser.add_dcmd_option(&_all);163_dcmdparser.add_dcmd_argument(&_cmd);164};165166167static int compare_strings(const char** s1, const char** s2) {168return ::strcmp(*s1, *s2);169}170171void HelpDCmd::execute(DCmdSource source, TRAPS) {172if (_all.value()) {173GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list(source);174cmd_list->sort(compare_strings);175for (int i = 0; i < cmd_list->length(); i++) {176DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),177strlen(cmd_list->at(i)));178output()->print_cr("%s%s", factory->name(),179factory->is_enabled() ? "" : " [disabled]");180output()->print_cr("\t%s", factory->description());181output()->cr();182factory = factory->next();183}184} else if (_cmd.has_value()) {185DCmd* cmd = NULL;186DCmdFactory* factory = DCmdFactory::factory(source, _cmd.value(),187strlen(_cmd.value()));188if (factory != NULL) {189output()->print_cr("%s%s", factory->name(),190factory->is_enabled() ? "" : " [disabled]");191output()->print_cr("%s", factory->description());192output()->print_cr("\nImpact: %s", factory->impact());193JavaPermission p = factory->permission();194if(p._class != NULL) {195if(p._action != NULL) {196output()->print_cr("\nPermission: %s(%s, %s)",197p._class, p._name == NULL ? "null" : p._name, p._action);198} else {199output()->print_cr("\nPermission: %s(%s)",200p._class, p._name == NULL ? "null" : p._name);201}202}203output()->cr();204cmd = factory->create_resource_instance(output());205if (cmd != NULL) {206DCmdMark mark(cmd);207cmd->print_help(factory->name());208}209} else {210output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value());211}212} else {213output()->print_cr("The following commands are available:");214GrowableArray<const char *>* cmd_list = DCmdFactory::DCmd_list(source);215cmd_list->sort(compare_strings);216for (int i = 0; i < cmd_list->length(); i++) {217DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),218strlen(cmd_list->at(i)));219output()->print_cr("%s%s", factory->name(),220factory->is_enabled() ? "" : " [disabled]");221factory = factory->_next;222}223output()->print_cr("\nFor more information about a specific command use 'help <command>'.");224}225}226227void VersionDCmd::execute(DCmdSource source, TRAPS) {228output()->print_cr("%s version %s", VM_Version::vm_name(),229VM_Version::vm_release());230JDK_Version jdk_version = JDK_Version::current();231if (jdk_version.patch_version() > 0) {232output()->print_cr("JDK %d.%d.%d.%d", jdk_version.major_version(),233jdk_version.minor_version(), jdk_version.security_version(),234jdk_version.patch_version());235} else {236output()->print_cr("JDK %d.%d.%d", jdk_version.major_version(),237jdk_version.minor_version(), jdk_version.security_version());238}239}240241PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) :242DCmdWithParser(output, heap),243_all("-all", "Print all flags supported by the VM", "BOOLEAN", false, "false") {244_dcmdparser.add_dcmd_option(&_all);245}246247void PrintVMFlagsDCmd::execute(DCmdSource source, TRAPS) {248if (_all.value()) {249JVMFlag::printFlags(output(), true);250} else {251JVMFlag::printSetFlags(output());252}253}254255SetVMFlagDCmd::SetVMFlagDCmd(outputStream* output, bool heap) :256DCmdWithParser(output, heap),257_flag("flag name", "The name of the flag we want to set",258"STRING", true),259_value("string value", "The value we want to set", "STRING", false) {260_dcmdparser.add_dcmd_argument(&_flag);261_dcmdparser.add_dcmd_argument(&_value);262}263264void SetVMFlagDCmd::execute(DCmdSource source, TRAPS) {265const char* val = NULL;266if (_value.value() != NULL) {267val = _value.value();268}269270FormatBuffer<80> err_msg("%s", "");271int ret = WriteableFlags::set_flag(_flag.value(), val, JVMFlagOrigin::MANAGEMENT, err_msg);272273if (ret != JVMFlag::SUCCESS) {274output()->print_cr("%s", err_msg.buffer());275}276}277278void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) {279if (JvmtiExport::should_post_data_dump()) {280JvmtiExport::post_data_dump();281}282}283284#if INCLUDE_SERVICES285#if INCLUDE_JVMTI286JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) :287DCmdWithParser(output, heap),288_libpath("library path", "Absolute path of the JVMTI agent to load.",289"STRING", true),290_option("agent option", "Option string to pass the agent.", "STRING", false) {291_dcmdparser.add_dcmd_argument(&_libpath);292_dcmdparser.add_dcmd_argument(&_option);293}294295void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) {296297if (_libpath.value() == NULL) {298output()->print_cr("JVMTI.agent_load dcmd needs library path.");299return;300}301302char *suffix = strrchr(_libpath.value(), '.');303bool is_java_agent = (suffix != NULL) && (strncmp(".jar", suffix, 4) == 0);304305if (is_java_agent) {306if (_option.value() == NULL) {307JvmtiExport::load_agent_library("instrument", "false",308_libpath.value(), output());309} else {310size_t opt_len = strlen(_libpath.value()) + strlen(_option.value()) + 2;311if (opt_len > 4096) {312output()->print_cr("JVMTI agent attach failed: Options is too long.");313return;314}315316char *opt = (char *)os::malloc(opt_len, mtInternal);317if (opt == NULL) {318output()->print_cr("JVMTI agent attach failed: "319"Could not allocate " SIZE_FORMAT " bytes for argument.",320opt_len);321return;322}323324jio_snprintf(opt, opt_len, "%s=%s", _libpath.value(), _option.value());325JvmtiExport::load_agent_library("instrument", "false", opt, output());326327os::free(opt);328}329} else {330JvmtiExport::load_agent_library(_libpath.value(), "true",331_option.value(), output());332}333}334335#endif // INCLUDE_JVMTI336#endif // INCLUDE_SERVICES337338void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {339// load VMSupport340Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport();341Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK);342InstanceKlass* ik = InstanceKlass::cast(k);343if (ik->should_be_initialized()) {344ik->initialize(THREAD);345}346if (HAS_PENDING_EXCEPTION) {347java_lang_Throwable::print(PENDING_EXCEPTION, output());348output()->cr();349CLEAR_PENDING_EXCEPTION;350return;351}352353// invoke the serializePropertiesToByteArray method354JavaValue result(T_OBJECT);355JavaCallArguments args;356357Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature();358JavaCalls::call_static(&result,359ik,360vmSymbols::serializePropertiesToByteArray_name(),361signature,362&args,363THREAD);364if (HAS_PENDING_EXCEPTION) {365java_lang_Throwable::print(PENDING_EXCEPTION, output());366output()->cr();367CLEAR_PENDING_EXCEPTION;368return;369}370371// The result should be a [B372oop res = result.get_oop();373assert(res->is_typeArray(), "just checking");374assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");375376// copy the bytes to the output stream377typeArrayOop ba = typeArrayOop(res);378jbyte* addr = typeArrayOop(res)->byte_at_addr(0);379output()->print_raw((const char*)addr, ba->length());380}381382VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :383DCmdWithParser(output, heap),384_date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {385_dcmdparser.add_dcmd_option(&_date);386}387388void VMUptimeDCmd::execute(DCmdSource source, TRAPS) {389if (_date.value()) {390output()->date_stamp(true, "", ": ");391}392output()->time_stamp().update_to(tty->time_stamp().ticks());393output()->stamp();394output()->print_cr(" s");395}396397void VMInfoDCmd::execute(DCmdSource source, TRAPS) {398VMError::print_vm_info(_output);399}400401void SystemGCDCmd::execute(DCmdSource source, TRAPS) {402Universe::heap()->collect(GCCause::_dcmd_gc_run);403}404405void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) {406Klass* k = vmClasses::System_klass();407JavaValue result(T_VOID);408JavaCalls::call_static(&result, k,409vmSymbols::run_finalization_name(),410vmSymbols::void_method_signature(), CHECK);411}412413void HeapInfoDCmd::execute(DCmdSource source, TRAPS) {414MutexLocker hl(THREAD, Heap_lock);415Universe::heap()->print_on(output());416}417418void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) {419ResourceMark rm(THREAD);420421Klass* k = SystemDictionary::resolve_or_fail(422vmSymbols::finalizer_histogram_klass(), true, CHECK);423424JavaValue result(T_ARRAY);425426// We are calling lang.ref.FinalizerHistogram.getFinalizerHistogram() method427// and expect it to return array of FinalizerHistogramEntry as Object[]428429JavaCalls::call_static(&result, k,430vmSymbols::get_finalizer_histogram_name(),431vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK);432433objArrayOop result_oop = (objArrayOop) result.get_oop();434if (result_oop->length() == 0) {435output()->print_cr("No instances waiting for finalization found");436return;437}438439oop foop = result_oop->obj_at(0);440InstanceKlass* ik = InstanceKlass::cast(foop->klass());441442fieldDescriptor count_fd, name_fd;443444Klass* count_res = ik->find_field(445vmSymbols::finalizer_histogram_entry_count_field(), vmSymbols::int_signature(), &count_fd);446447Klass* name_res = ik->find_field(448vmSymbols::finalizer_histogram_entry_name_field(), vmSymbols::string_signature(), &name_fd);449450assert(count_res != NULL && name_res != NULL, "Unexpected layout of FinalizerHistogramEntry");451452output()->print_cr("Unreachable instances waiting for finalization");453output()->print_cr("#instances class name");454output()->print_cr("-----------------------");455456for (int i = 0; i < result_oop->length(); ++i) {457oop element_oop = result_oop->obj_at(i);458oop str_oop = element_oop->obj_field(name_fd.offset());459char *name = java_lang_String::as_utf8_string(str_oop);460int count = element_oop->int_field(count_fd.offset());461output()->print_cr("%10d %s", count, name);462}463}464465#if INCLUDE_SERVICES // Heap dumping/inspection supported466HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :467DCmdWithParser(output, heap),468_filename("filename","Name of the dump file", "STRING",true),469_all("-all", "Dump all objects, including unreachable objects",470"BOOLEAN", false, "false"),471_gzip("-gz", "If specified, the heap dump is written in gzipped format "472"using the given compression level. 1 (recommended) is the fastest, "473"9 the strongest compression.", "INT", false, "1"),474_overwrite("-overwrite", "If specified, the dump file will be overwritten if it exists",475"BOOLEAN", false, "false") {476_dcmdparser.add_dcmd_option(&_all);477_dcmdparser.add_dcmd_argument(&_filename);478_dcmdparser.add_dcmd_option(&_gzip);479_dcmdparser.add_dcmd_option(&_overwrite);480}481482void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {483jlong level = -1; // -1 means no compression.484485if (_gzip.is_set()) {486level = _gzip.value();487488if (level < 1 || level > 9) {489output()->print_cr("Compression level out of range (1-9): " JLONG_FORMAT, level);490return;491}492}493494// Request a full GC before heap dump if _all is false495// This helps reduces the amount of unreachable objects in the dump496// and makes it easier to browse.497HeapDumper dumper(!_all.value() /* request GC if _all is false*/);498dumper.dump(_filename.value(), output(), (int) level, _overwrite.value());499}500501ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :502DCmdWithParser(output, heap),503_all("-all", "Inspect all objects, including unreachable objects",504"BOOLEAN", false, "false"),505_parallel_thread_num("-parallel",506"Number of parallel threads to use for heap inspection. "507"0 (the default) means let the VM determine the number of threads to use. "508"1 means use one thread (disable parallelism). "509"For any other value the VM will try to use the specified number of "510"threads, but might use fewer.",511"INT", false, "0") {512_dcmdparser.add_dcmd_option(&_all);513_dcmdparser.add_dcmd_option(&_parallel_thread_num);514}515516void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) {517jlong num = _parallel_thread_num.value();518if (num < 0) {519output()->print_cr("Parallel thread number out of range (>=0): " JLONG_FORMAT, num);520return;521}522uint parallel_thread_num = num == 0523? MAX2<uint>(1, (uint)os::initial_active_processor_count() * 3 / 8)524: num;525VM_GC_HeapInspection heapop(output(),526!_all.value(), /* request full gc if false */527parallel_thread_num);528VMThread::execute(&heapop);529}530531#endif // INCLUDE_SERVICES532533ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :534DCmdWithParser(output, heap),535_locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false"),536_extended("-e", "print extended thread information", "BOOLEAN", false, "false") {537_dcmdparser.add_dcmd_option(&_locks);538_dcmdparser.add_dcmd_option(&_extended);539}540541void ThreadDumpDCmd::execute(DCmdSource source, TRAPS) {542// thread stacks543VM_PrintThreads op1(output(), _locks.value(), _extended.value());544VMThread::execute(&op1);545546// JNI global handles547VM_PrintJNI op2(output());548VMThread::execute(&op2);549550// Deadlock detection551VM_FindDeadlocks op3(output());552VMThread::execute(&op3);553}554555// Enhanced JMX Agent support556557JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated) :558559DCmdWithParser(output, heap_allocated),560561_config_file562("config.file",563"set com.sun.management.config.file", "STRING", false),564565_jmxremote_host566("jmxremote.host",567"set com.sun.management.jmxremote.host", "STRING", false),568569_jmxremote_port570("jmxremote.port",571"set com.sun.management.jmxremote.port", "STRING", false),572573_jmxremote_rmi_port574("jmxremote.rmi.port",575"set com.sun.management.jmxremote.rmi.port", "STRING", false),576577_jmxremote_ssl578("jmxremote.ssl",579"set com.sun.management.jmxremote.ssl", "STRING", false),580581_jmxremote_registry_ssl582("jmxremote.registry.ssl",583"set com.sun.management.jmxremote.registry.ssl", "STRING", false),584585_jmxremote_authenticate586("jmxremote.authenticate",587"set com.sun.management.jmxremote.authenticate", "STRING", false),588589_jmxremote_password_file590("jmxremote.password.file",591"set com.sun.management.jmxremote.password.file", "STRING", false),592593_jmxremote_access_file594("jmxremote.access.file",595"set com.sun.management.jmxremote.access.file", "STRING", false),596597_jmxremote_login_config598("jmxremote.login.config",599"set com.sun.management.jmxremote.login.config", "STRING", false),600601_jmxremote_ssl_enabled_cipher_suites602("jmxremote.ssl.enabled.cipher.suites",603"set com.sun.management.jmxremote.ssl.enabled.cipher.suite", "STRING", false),604605_jmxremote_ssl_enabled_protocols606("jmxremote.ssl.enabled.protocols",607"set com.sun.management.jmxremote.ssl.enabled.protocols", "STRING", false),608609_jmxremote_ssl_need_client_auth610("jmxremote.ssl.need.client.auth",611"set com.sun.management.jmxremote.need.client.auth", "STRING", false),612613_jmxremote_ssl_config_file614("jmxremote.ssl.config.file",615"set com.sun.management.jmxremote.ssl.config.file", "STRING", false),616617// JDP Protocol support618_jmxremote_autodiscovery619("jmxremote.autodiscovery",620"set com.sun.management.jmxremote.autodiscovery", "STRING", false),621622_jdp_port623("jdp.port",624"set com.sun.management.jdp.port", "INT", false),625626_jdp_address627("jdp.address",628"set com.sun.management.jdp.address", "STRING", false),629630_jdp_source_addr631("jdp.source_addr",632"set com.sun.management.jdp.source_addr", "STRING", false),633634_jdp_ttl635("jdp.ttl",636"set com.sun.management.jdp.ttl", "INT", false),637638_jdp_pause639("jdp.pause",640"set com.sun.management.jdp.pause", "INT", false),641642_jdp_name643("jdp.name",644"set com.sun.management.jdp.name", "STRING", false)645646{647_dcmdparser.add_dcmd_option(&_config_file);648_dcmdparser.add_dcmd_option(&_jmxremote_host);649_dcmdparser.add_dcmd_option(&_jmxremote_port);650_dcmdparser.add_dcmd_option(&_jmxremote_rmi_port);651_dcmdparser.add_dcmd_option(&_jmxremote_ssl);652_dcmdparser.add_dcmd_option(&_jmxremote_registry_ssl);653_dcmdparser.add_dcmd_option(&_jmxremote_authenticate);654_dcmdparser.add_dcmd_option(&_jmxremote_password_file);655_dcmdparser.add_dcmd_option(&_jmxremote_access_file);656_dcmdparser.add_dcmd_option(&_jmxremote_login_config);657_dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_cipher_suites);658_dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);659_dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);660_dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);661_dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery);662_dcmdparser.add_dcmd_option(&_jdp_port);663_dcmdparser.add_dcmd_option(&_jdp_address);664_dcmdparser.add_dcmd_option(&_jdp_source_addr);665_dcmdparser.add_dcmd_option(&_jdp_ttl);666_dcmdparser.add_dcmd_option(&_jdp_pause);667_dcmdparser.add_dcmd_option(&_jdp_name);668}669670void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {671ResourceMark rm(THREAD);672HandleMark hm(THREAD);673674// Load and initialize the jdk.internal.agent.Agent class675// invoke startRemoteManagementAgent(string) method to start676// the remote management server.677// throw java.lang.NoSuchMethodError if the method doesn't exist678679loadAgentModule(CHECK);680Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());681Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);682683JavaValue result(T_VOID);684685// Pass all command line arguments to java as key=value,...686// All checks are done on java side687688int len = 0;689stringStream options;690char comma[2] = {0,0};691692// Leave default values on Agent.class side and pass only693// agruments explicitly set by user. All arguments passed694// to jcmd override properties with the same name set by695// command line with -D or by managmenent.properties696// file.697#define PUT_OPTION(a) \698do { \699if ( (a).is_set() ){ \700if ( *((a).type()) == 'I' ) { \701options.print("%scom.sun.management.%s=" JLONG_FORMAT, comma, (a).name(), (jlong)((a).value())); \702} else { \703options.print("%scom.sun.management.%s=%s", comma, (a).name(), (char*)((a).value())); \704} \705comma[0] = ','; \706}\707} while(0);708709710PUT_OPTION(_config_file);711PUT_OPTION(_jmxremote_host);712PUT_OPTION(_jmxremote_port);713PUT_OPTION(_jmxremote_rmi_port);714PUT_OPTION(_jmxremote_ssl);715PUT_OPTION(_jmxremote_registry_ssl);716PUT_OPTION(_jmxremote_authenticate);717PUT_OPTION(_jmxremote_password_file);718PUT_OPTION(_jmxremote_access_file);719PUT_OPTION(_jmxremote_login_config);720PUT_OPTION(_jmxremote_ssl_enabled_cipher_suites);721PUT_OPTION(_jmxremote_ssl_enabled_protocols);722PUT_OPTION(_jmxremote_ssl_need_client_auth);723PUT_OPTION(_jmxremote_ssl_config_file);724PUT_OPTION(_jmxremote_autodiscovery);725PUT_OPTION(_jdp_port);726PUT_OPTION(_jdp_address);727PUT_OPTION(_jdp_source_addr);728PUT_OPTION(_jdp_ttl);729PUT_OPTION(_jdp_pause);730PUT_OPTION(_jdp_name);731732#undef PUT_OPTION733734Handle str = java_lang_String::create_from_str(options.as_string(), CHECK);735JavaCalls::call_static(&result, k, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK);736}737738JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) :739DCmd(output, heap_allocated) {740// do nothing741}742743void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {744ResourceMark rm(THREAD);745HandleMark hm(THREAD);746747// Load and initialize the jdk.internal.agent.Agent class748// invoke startLocalManagementAgent(void) method to start749// the local management server750// throw java.lang.NoSuchMethodError if method doesn't exist751752loadAgentModule(CHECK);753Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());754Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);755756JavaValue result(T_VOID);757JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);758}759760void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) {761ResourceMark rm(THREAD);762HandleMark hm(THREAD);763764// Load and initialize the jdk.internal.agent.Agent class765// invoke stopRemoteManagementAgent method to stop the766// management server767// throw java.lang.NoSuchMethodError if method doesn't exist768769loadAgentModule(CHECK);770Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());771Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);772773JavaValue result(T_VOID);774JavaCalls::call_static(&result, k, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);775}776777JMXStatusDCmd::JMXStatusDCmd(outputStream *output, bool heap_allocated) :778DCmd(output, heap_allocated) {779// do nothing780}781782void JMXStatusDCmd::execute(DCmdSource source, TRAPS) {783ResourceMark rm(THREAD);784HandleMark hm(THREAD);785786// Load and initialize the jdk.internal.agent.Agent class787// invoke getManagementAgentStatus() method to generate the status info788// throw java.lang.NoSuchMethodError if method doesn't exist789790loadAgentModule(CHECK);791Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());792Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);793794JavaValue result(T_OBJECT);795JavaCalls::call_static(&result, k, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK);796797jvalue* jv = (jvalue*) result.get_value_addr();798oop str = cast_to_oop(jv->l);799if (str != NULL) {800char* out = java_lang_String::as_utf8_string(str);801if (out) {802output()->print_cr("%s", out);803return;804}805}806output()->print_cr("Error obtaining management agent status");807}808809VMDynamicLibrariesDCmd::VMDynamicLibrariesDCmd(outputStream *output, bool heap_allocated) :810DCmd(output, heap_allocated) {811// do nothing812}813814void VMDynamicLibrariesDCmd::execute(DCmdSource source, TRAPS) {815os::print_dll_info(output());816output()->cr();817}818819void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {820VM_PrintCompileQueue printCompileQueueOp(output());821VMThread::execute(&printCompileQueueOp);822}823824void CodeListDCmd::execute(DCmdSource source, TRAPS) {825CodeCache::print_codelist(output());826}827828void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {829CodeCache::print_layout(output());830}831832#ifdef LINUX833void PerfMapDCmd::execute(DCmdSource source, TRAPS) {834CodeCache::write_perf_map();835}836#endif // LINUX837838//---< BEGIN >--- CodeHeap State Analytics.839CodeHeapAnalyticsDCmd::CodeHeapAnalyticsDCmd(outputStream* output, bool heap) :840DCmdWithParser(output, heap),841_function("function", "Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard", "STRING", false, "all"),842_granularity("granularity", "Detail level - smaller value -> more detail", "INT", false, "4096") {843_dcmdparser.add_dcmd_argument(&_function);844_dcmdparser.add_dcmd_argument(&_granularity);845}846847void CodeHeapAnalyticsDCmd::execute(DCmdSource source, TRAPS) {848jlong granularity = _granularity.value();849if (granularity < 1) {850Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),851"Invalid granularity value " JLONG_FORMAT ". Should be positive.\n", granularity);852return;853}854855CompileBroker::print_heapinfo(output(), _function.value(), granularity);856}857//---< END >--- CodeHeap State Analytics.858859EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) :860DCmdWithParser(output, heap),861_log("log", "Name of log to be printed. If omitted, all logs are printed.", "STRING", false, NULL),862_max("max", "Maximum number of events to be printed (newest first). If omitted, all events are printed.", "STRING", false, NULL)863{864_dcmdparser.add_dcmd_option(&_log);865_dcmdparser.add_dcmd_option(&_max);866}867868void EventLogDCmd::execute(DCmdSource source, TRAPS) {869const char* max_value = _max.value();870long max = -1;871if (max_value != NULL) {872char* endptr = NULL;873max = ::strtol(max_value, &endptr, 10);874if (max == 0 && max_value == endptr) {875output()->print_cr("Invalid max option: \"%s\".", max_value);876return;877}878}879const char* log_name = _log.value();880if (log_name != NULL) {881Events::print_one(output(), log_name, max);882} else {883Events::print_all(output(), max);884}885}886887void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) {888DirectivesStack::print(output());889}890891CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool heap) :892DCmdWithParser(output, heap),893_filename("filename","Name of the directives file", "STRING",true) {894_dcmdparser.add_dcmd_argument(&_filename);895}896897void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) {898DirectivesParser::parse_from_file(_filename.value(), output());899}900901void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {902DirectivesStack::pop(1);903}904905void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {906DirectivesStack::clear();907}908#if INCLUDE_SERVICES909ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :910DCmdWithParser(output, heap),911_print_interfaces("-i", "Inherited interfaces should be printed.", "BOOLEAN", false, "false"),912_print_subclasses("-s", "If a classname is specified, print its subclasses. "913"Otherwise only its superclasses are printed.", "BOOLEAN", false, "false"),914_classname("classname", "Name of class whose hierarchy should be printed. "915"If not specified, all class hierarchies are printed.",916"STRING", false) {917_dcmdparser.add_dcmd_option(&_print_interfaces);918_dcmdparser.add_dcmd_option(&_print_subclasses);919_dcmdparser.add_dcmd_argument(&_classname);920}921922void ClassHierarchyDCmd::execute(DCmdSource source, TRAPS) {923VM_PrintClassHierarchy printClassHierarchyOp(output(), _print_interfaces.value(),924_print_subclasses.value(), _classname.value());925VMThread::execute(&printClassHierarchyOp);926}927#endif928929class VM_DumpTouchedMethods : public VM_Operation {930private:931outputStream* _out;932public:933VM_DumpTouchedMethods(outputStream* out) {934_out = out;935}936937virtual VMOp_Type type() const { return VMOp_DumpTouchedMethods; }938939virtual void doit() {940Method::print_touched_methods(_out);941}942};943944void TouchedMethodsDCmd::execute(DCmdSource source, TRAPS) {945if (!LogTouchedMethods) {946output()->print_cr("VM.print_touched_methods command requires -XX:+LogTouchedMethods");947return;948}949VM_DumpTouchedMethods dumper(output());950VMThread::execute(&dumper);951}952953#if INCLUDE_CDS954DumpSharedArchiveDCmd::DumpSharedArchiveDCmd(outputStream* output, bool heap) :955DCmdWithParser(output, heap),956_suboption("subcmd", "static_dump | dynamic_dump", "STRING", true),957_filename("filename", "Name of shared archive to be dumped", "STRING", false)958{959_dcmdparser.add_dcmd_argument(&_suboption);960_dcmdparser.add_dcmd_argument(&_filename);961}962963void DumpSharedArchiveDCmd::execute(DCmdSource source, TRAPS) {964jboolean is_static;965const char* scmd = _suboption.value();966const char* file = _filename.value();967968if (strcmp(scmd, "static_dump") == 0) {969is_static = JNI_TRUE;970output()->print_cr("Static dump:");971} else if (strcmp(scmd, "dynamic_dump") == 0) {972is_static = JNI_FALSE;973output()->print_cr("Dynamic dump:");974if (!UseSharedSpaces) {975output()->print_cr("Dynamic dump is unsupported when base CDS archive is not loaded");976return;977}978if (!RecordDynamicDumpInfo) {979output()->print_cr("Dump dynamic should run with -XX:+RecordDynamicDumpInfo");980return;981}982} else {983output()->print_cr("Invalid command for VM.cds, valid input is static_dump or dynamic_dump");984return;985}986987// call CDS.dumpSharedArchive988Handle fileh;989if (file != NULL) {990fileh = java_lang_String::create_from_str(_filename.value(), CHECK);991}992Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();993Klass* cds_klass = SystemDictionary::resolve_or_fail(cds_name, true /*throw error*/, CHECK);994JavaValue result(T_VOID);995JavaCallArguments args;996args.push_int(is_static);997args.push_oop(fileh);998JavaCalls::call_static(&result,999cds_klass,1000vmSymbols::dumpSharedArchive(),1001vmSymbols::dumpSharedArchive_signature(),1002&args, CHECK);1003}1004#endif // INCLUDE_CDS10051006#if INCLUDE_JVMTI1007extern "C" typedef char const* (JNICALL *debugInit_startDebuggingViaCommandPtr)(JNIEnv* env, jthread thread, char const** transport_name,1008char const** address, jboolean* first_start);1009static debugInit_startDebuggingViaCommandPtr dvc_start_ptr = NULL;10101011void DebugOnCmdStartDCmd::execute(DCmdSource source, TRAPS) {1012char const* transport = NULL;1013char const* addr = NULL;1014jboolean is_first_start = JNI_FALSE;1015JavaThread* thread = THREAD;1016jthread jt = JNIHandles::make_local(thread->threadObj());1017ThreadToNativeFromVM ttn(thread);1018const char *error = "Could not find jdwp agent.";10191020if (!dvc_start_ptr) {1021for (AgentLibrary* agent = Arguments::agents(); agent != NULL; agent = agent->next()) {1022if ((strcmp("jdwp", agent->name()) == 0) && (dvc_start_ptr == NULL)) {1023char const* func = "debugInit_startDebuggingViaCommand";1024dvc_start_ptr = (debugInit_startDebuggingViaCommandPtr) os::find_agent_function(agent, false, &func, 1);1025}1026}1027}10281029if (dvc_start_ptr) {1030error = dvc_start_ptr(thread->jni_environment(), jt, &transport, &addr, &is_first_start);1031}10321033if (error != NULL) {1034output()->print_cr("Debugging has not been started: %s", error);1035} else {1036output()->print_cr(is_first_start ? "Debugging has been started." : "Debugging is already active.");1037output()->print_cr("Transport : %s", transport ? transport : "#unknown");1038output()->print_cr("Address : %s", addr ? addr : "#unknown");1039}1040}1041#endif // INCLUDE_JVMTI104210431044