/* * Copyright (c) 2011, 2022, 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. *
*/
// Enhanced JMX Agent Support // These commands won't be exported via the DiagnosticCommandMBean until an // appropriate permission is created for them
uint32_t jmx_agent_export_flags = DCmd_Source_Internal | DCmd_Source_AttachAPI;
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(jmx_agent_export_flags, true,false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(jmx_agent_export_flags, true,false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(jmx_agent_export_flags, true,false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStatusDCmd>(jmx_agent_export_flags, true,false));
// Debug on cmd (only makes sense with JVMTI since the agentlib needs it). #if INCLUDE_JVMTI
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DebugOnCmdStartDCmd>(full_export, true, true)); #endif// INCLUDE_JVMTI
#ifndef HAVE_EXTRA_DCMD void DCmdRegistrant::register_dcmds_ext(){ // Do nothing here
} #endif
HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
_all("-all", "Show help for all commands", "BOOLEAN", false, "false"),
_cmd("command name", "The name of the command for which we want help", "STRING", false) {
_dcmdparser.add_dcmd_option(&_all);
_dcmdparser.add_dcmd_argument(&_cmd);
};
SetVMFlagDCmd::SetVMFlagDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_flag("flag name", "The name of the flag we want to set", "STRING", true),
_value("string value", "The value we want to set", "STRING", false) {
_dcmdparser.add_dcmd_argument(&_flag);
_dcmdparser.add_dcmd_argument(&_value);
}
void SetVMFlagDCmd::execute(DCmdSource source, TRAPS) { constchar* val = NULL; if (_value.value() != NULL) {
val = _value.value();
}
FormatBuffer<80> err_msg("%s", ""); int ret = WriteableFlags::set_flag(_flag.value(), val, JVMFlagOrigin::MANAGEMENT, err_msg);
if (ret != JVMFlag::SUCCESS) {
output()->print_cr("%s", err_msg.buffer());
}
}
// The result should be a [B
oop res = result.get_oop();
assert(res->is_typeArray(), "just checking");
assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
// copy the bytes to the output stream
typeArrayOop ba = typeArrayOop(res);
jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
output()->print_raw((constchar*)addr, ba->length());
}
VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_date);
}
output()->print_cr("Unreachable instances waiting for finalization");
output()->print_cr("#instances class name");
output()->print_cr("-----------------------");
for (int i = 0; i < result_oop->length(); ++i) {
oop element_oop = result_oop->obj_at(i);
oop str_oop = element_oop->obj_field(name_fd.offset()); char *name = java_lang_String::as_utf8_string(str_oop); int count = element_oop->int_field(count_fd.offset());
output()->print_cr("%10d %s", count, name);
}
}
#if INCLUDE_SERVICES // Heap dumping/inspection supported
HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_filename("filename","Name of the dump file", "STRING",true),
_all("-all", "Dump all objects, including unreachable objects", "BOOLEAN", false, "false"),
_gzip("-gz", "If specified, the heap dump is written in gzipped format " "using the given compression level. 1 (recommended) is the fastest, " "9 the strongest compression.", "INT", false, "1"),
_overwrite("-overwrite", "If specified, the dump file will be overwritten if it exists", "BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_all);
_dcmdparser.add_dcmd_argument(&_filename);
_dcmdparser.add_dcmd_option(&_gzip);
_dcmdparser.add_dcmd_option(&_overwrite);
}
void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
jlong level = -1; // -1 means no compression.
if (_gzip.is_set()) {
level = _gzip.value();
if (level < 1 || level > 9) {
output()->print_cr("Compression level out of range (1-9): " JLONG_FORMAT, level); return;
}
}
// Request a full GC before heap dump if _all is false // This helps reduces the amount of unreachable objects in the dump // and makes it easier to browse.
HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
dumper.dump(_filename.value(), output(), (int) level, _overwrite.value());
}
ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_all("-all", "Inspect all objects, including unreachable objects", "BOOLEAN", false, "false"),
_parallel_thread_num("-parallel", "Number of parallel threads to use for heap inspection. " "0 (the default) means let the VM determine the number of threads to use. " "1 means use one thread (disable parallelism). " "For any other value the VM will try to use the specified number of " "threads, but might use fewer.", "INT", false, "0") {
_dcmdparser.add_dcmd_option(&_all);
_dcmdparser.add_dcmd_option(&_parallel_thread_num);
}
void ClassHistogramDCmd::execute(DCmdSource source, TRAPS) {
jlong num = _parallel_thread_num.value(); if (num < 0) {
output()->print_cr("Parallel thread number out of range (>=0): " JLONG_FORMAT, num); return;
}
uint parallel_thread_num = num == 0
? MAX2<uint>(1, (uint)os::initial_active_processor_count() * 3 / 8)
: num;
VM_GC_HeapInspection heapop(output(),
!_all.value(), /* request full gc if false */
parallel_thread_num);
VMThread::execute(&heapop);
}
// Load and initialize the jdk.internal.agent.Agent class // invoke startRemoteManagementAgent(string) method to start // the remote management server. // throw java.lang.NoSuchMethodError if the method doesn't exist
// Pass all command line arguments to java as key=value,... // All checks are done on java side
int len = 0;
stringStream options; char comma[2] = {0,0};
// Leave default values on Agent.class side and pass only // arguments explicitly set by user. All arguments passed // to jcmd override properties with the same name set by // command line with -D or by managmenent.properties // file. #define PUT_OPTION(a) \ do { \ if ( (a).is_set() ){ \ if ( *((a).type()) == 'I' ) { \
options.print("%scom.sun.management.%s=" JLONG_FORMAT, comma, (a).name(), (jlong)((a).value())); \
} else { \
options.print("%scom.sun.management.%s=%s", comma, (a).name(), (char*)((a).value())); \
} \
comma[0] = ','; \
}\
} while(0);
// Load and initialize the jdk.internal.agent.Agent class // invoke startLocalManagementAgent(void) method to start // the local management server // throw java.lang.NoSuchMethodError if method doesn't exist
// Load and initialize the jdk.internal.agent.Agent class // invoke stopRemoteManagementAgent method to stop the // management server // throw java.lang.NoSuchMethodError if method doesn't exist
// Load and initialize the jdk.internal.agent.Agent class // invoke getManagementAgentStatus() method to generate the status info // throw java.lang.NoSuchMethodError if method doesn't exist
#ifdef LINUX void PerfMapDCmd::execute(DCmdSource source, TRAPS) {
CodeCache::write_perf_map();
} #endif// LINUX
//---< BEGIN >--- CodeHeap State Analytics.
CodeHeapAnalyticsDCmd::CodeHeapAnalyticsDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_function("function", "Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard", "STRING", false, "all"),
_granularity("granularity", "Detail level - smaller value -> more detail", "INT", false, "4096") {
_dcmdparser.add_dcmd_argument(&_function);
_dcmdparser.add_dcmd_argument(&_granularity);
}
void CodeHeapAnalyticsDCmd::execute(DCmdSource source, TRAPS) {
jlong granularity = _granularity.value(); if (granularity < 1) {
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(), "Invalid granularity value " JLONG_FORMAT ". Should be positive.\n", granularity); return;
}
CompileBroker::print_heapinfo(output(), _function.value(), granularity);
} //---< END >--- CodeHeap State Analytics.
EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_log("log", "Name of log to be printed. If omitted, all logs are printed.", "STRING", false, NULL),
_max("max", "Maximum number of events to be printed (newest first). If omitted, all events are printed.", "STRING", false, NULL)
{
_dcmdparser.add_dcmd_option(&_log);
_dcmdparser.add_dcmd_option(&_max);
}
void EventLogDCmd::execute(DCmdSource source, TRAPS) { constchar* max_value = _max.value(); long max = -1; if (max_value != NULL) { char* endptr = NULL;
max = ::strtol(max_value, &endptr, 10); if (max == 0 && max_value == endptr) {
output()->print_cr("Invalid max option: \"%s\".", max_value); return;
}
} constchar* log_name = _log.value(); if (log_name != NULL) {
Events::print_one(output(), log_name, max);
} else {
Events::print_all(output(), max);
}
}
void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {
DirectivesStack::clear();
} #if INCLUDE_SERVICES
ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_print_interfaces("-i", "Inherited interfaces should be printed.", "BOOLEAN", false, "false"),
_print_subclasses("-s", "If a classname is specified, print its subclasses " "in addition to its superclasses. Without this option only the " "superclasses will be printed.", "BOOLEAN", false, "false"),
_classname("classname", "Name of class whose hierarchy should be printed. " "If not specified, all class hierarchies are printed.", "STRING", false) {
_dcmdparser.add_dcmd_option(&_print_interfaces);
_dcmdparser.add_dcmd_option(&_print_subclasses);
_dcmdparser.add_dcmd_argument(&_classname);
}
if (strcmp(scmd, "static_dump") == 0) {
is_static = JNI_TRUE;
output()->print("Static dump: ");
} elseif (strcmp(scmd, "dynamic_dump") == 0) {
is_static = JNI_FALSE;
output()->print("Dynamic dump: "); if (!UseSharedSpaces) {
output()->print_cr("Dynamic dump is unsupported when base CDS archive is not loaded"); return;
} if (!RecordDynamicDumpInfo) {
output()->print_cr("Dump dynamic should run with -XX:+RecordDynamicDumpInfo"); return;
}
} else {
output()->print_cr("Invalid command for VM.cds, valid input is static_dump or dynamic_dump"); return;
}
Symbol* sym = vmSymbols::jdk_internal_vm_ThreadDumper();
Klass* k = SystemDictionary::resolve_or_fail(sym, true, CHECK);
InstanceKlass* ik = InstanceKlass::cast(k); if (HAS_PENDING_EXCEPTION) {
java_lang_Throwable::print(PENDING_EXCEPTION, output());
output()->cr();
CLEAR_PENDING_EXCEPTION; return;
}
// invoke the ThreadDump method to dump to file
JavaValue result(T_OBJECT);
JavaCallArguments args;
args.push_oop(h_path);
args.push_int(overwrite ? JNI_TRUE : JNI_FALSE);
JavaCalls::call_static(&result,
k,
name,
signature,
&args,
THREAD); if (HAS_PENDING_EXCEPTION) {
java_lang_Throwable::print(PENDING_EXCEPTION, output());
output()->cr();
CLEAR_PENDING_EXCEPTION; return;
}
// check that result is byte array
oop res = cast_to_oop(result.get_jobject());
assert(res->is_typeArray(), "just checking");
assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
// copy the bytes to the output stream
typeArrayOop ba = typeArrayOop(res);
jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
output()->print_raw((constchar*)addr, ba->length());
}
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.