1 /* 2 * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/javaClasses.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "gc/shared/vmGCOperations.hpp" 29 #include "memory/resourceArea.hpp" 30 #include "oops/oop.inline.hpp" 31 #include "oops/typeArrayOop.inline.hpp" 32 #include "prims/jvmtiExport.hpp" 33 #include "runtime/arguments.hpp" 34 #include "runtime/globals.hpp" 35 #include "runtime/handles.inline.hpp" 36 #include "runtime/java.hpp" 37 #include "runtime/javaCalls.hpp" 38 #include "runtime/os.hpp" 39 #include "services/attachListener.hpp" 40 #include "services/diagnosticCommand.hpp" 41 #include "services/heapDumper.hpp" 42 #include "services/writeableFlags.hpp" 43 #include "utilities/debug.hpp" 44 #include "utilities/formatBuffer.hpp" 45 46 volatile bool AttachListener::_initialized; 47 48 // Implementation of "properties" command. 49 // 50 // Invokes VMSupport.serializePropertiesToByteArray to serialize 51 // the system properties into a byte array. 52 53 static InstanceKlass* load_and_initialize_klass(Symbol* sh, TRAPS) { 54 Klass* k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL); 55 InstanceKlass* ik = InstanceKlass::cast(k); 56 if (ik->should_be_initialized()) { 57 ik->initialize(CHECK_NULL); 58 } 59 return ik; 60 } 61 62 static jint get_properties(AttachOperation* op, outputStream* out, Symbol* serializePropertiesMethod) { 63 Thread* THREAD = Thread::current(); 64 HandleMark hm; 65 66 // load VMSupport 67 Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport(); 68 InstanceKlass* k = load_and_initialize_klass(klass, THREAD); 69 if (HAS_PENDING_EXCEPTION) { 70 java_lang_Throwable::print(PENDING_EXCEPTION, out); 71 CLEAR_PENDING_EXCEPTION; 72 return JNI_ERR; 73 } 74 75 // invoke the serializePropertiesToByteArray method 76 JavaValue result(T_OBJECT); 77 JavaCallArguments args; 78 79 80 Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature(); 81 JavaCalls::call_static(&result, 82 k, 83 serializePropertiesMethod, 84 signature, 85 &args, 86 THREAD); 87 if (HAS_PENDING_EXCEPTION) { 88 java_lang_Throwable::print(PENDING_EXCEPTION, out); 89 CLEAR_PENDING_EXCEPTION; 90 return JNI_ERR; 91 } 92 93 // The result should be a [B 94 oop res = (oop)result.get_jobject(); 95 assert(res->is_typeArray(), "just checking"); 96 assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking"); 97 98 // copy the bytes to the output stream 99 typeArrayOop ba = typeArrayOop(res); 100 jbyte* addr = typeArrayOop(res)->byte_at_addr(0); 101 out->print_raw((const char*)addr, ba->length()); 102 103 return JNI_OK; 104 } 105 106 // Implementation of "load" command. 107 static jint load_agent(AttachOperation* op, outputStream* out) { 108 // get agent name and options 109 const char* agent = op->arg(0); 110 const char* absParam = op->arg(1); 111 const char* options = op->arg(2); 112 113 // If loading a java agent then need to ensure that the java.instrument module is loaded 114 if (strcmp(agent, "instrument") == 0) { 115 Thread* THREAD = Thread::current(); 116 ResourceMark rm(THREAD); 117 HandleMark hm(THREAD); 118 JavaValue result(T_OBJECT); 119 Handle h_module_name = java_lang_String::create_from_str("java.instrument", THREAD); 120 JavaCalls::call_static(&result, 121 SystemDictionary::module_Modules_klass(), 122 vmSymbols::loadModule_name(), 123 vmSymbols::loadModule_signature(), 124 h_module_name, 125 THREAD); 126 if (HAS_PENDING_EXCEPTION) { 127 java_lang_Throwable::print(PENDING_EXCEPTION, out); 128 CLEAR_PENDING_EXCEPTION; 129 return JNI_ERR; 130 } 131 } 132 133 return JvmtiExport::load_agent_library(agent, absParam, options, out); 134 } 135 136 // Implementation of "properties" command. 137 // See also: PrintSystemPropertiesDCmd class 138 static jint get_system_properties(AttachOperation* op, outputStream* out) { 139 return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name()); 140 } 141 142 // Implementation of "agent_properties" command. 143 static jint get_agent_properties(AttachOperation* op, outputStream* out) { 144 return get_properties(op, out, vmSymbols::serializeAgentPropertiesToByteArray_name()); 145 } 146 147 // Implementation of "datadump" command. 148 // 149 // Raises a SIGBREAK signal so that VM dump threads, does deadlock detection, 150 // etc. In theory this command should only post a DataDumpRequest to any 151 // JVMTI environment that has enabled this event. However it's useful to 152 // trigger the SIGBREAK handler. 153 154 static jint data_dump(AttachOperation* op, outputStream* out) { 155 if (!ReduceSignalUsage) { 156 AttachListener::pd_data_dump(); 157 } else { 158 if (JvmtiExport::should_post_data_dump()) { 159 JvmtiExport::post_data_dump(); 160 } 161 } 162 return JNI_OK; 163 } 164 165 // Implementation of "threaddump" command - essentially a remote ctrl-break 166 // See also: ThreadDumpDCmd class 167 // 168 static jint thread_dump(AttachOperation* op, outputStream* out) { 169 bool print_concurrent_locks = false; 170 if (op->arg(0) != NULL && strcmp(op->arg(0), "-l") == 0) { 171 print_concurrent_locks = true; 172 } 173 174 // thread stacks 175 VM_PrintThreads op1(out, print_concurrent_locks); 176 VMThread::execute(&op1); 177 178 // JNI global handles 179 VM_PrintJNI op2(out); 180 VMThread::execute(&op2); 181 182 // Deadlock detection 183 VM_FindDeadlocks op3(out); 184 VMThread::execute(&op3); 185 186 return JNI_OK; 187 } 188 189 // A jcmd attach operation request was received, which will now 190 // dispatch to the diagnostic commands used for serviceability functions. 191 static jint jcmd(AttachOperation* op, outputStream* out) { 192 Thread* THREAD = Thread::current(); 193 // All the supplied jcmd arguments are stored as a single 194 // string (op->arg(0)). This is parsed by the Dcmd framework. 195 DCmd::parse_and_execute(DCmd_Source_AttachAPI, out, op->arg(0), ' ', THREAD); 196 if (HAS_PENDING_EXCEPTION) { 197 java_lang_Throwable::print(PENDING_EXCEPTION, out); 198 out->cr(); 199 CLEAR_PENDING_EXCEPTION; 200 return JNI_ERR; 201 } 202 return JNI_OK; 203 } 204 205 // Implementation of "dumpheap" command. 206 // See also: HeapDumpDCmd class 207 // 208 // Input arguments :- 209 // arg0: Name of the dump file 210 // arg1: "-live" or "-all" 211 jint dump_heap(AttachOperation* op, outputStream* out) { 212 const char* path = op->arg(0); 213 if (path == NULL || path[0] == '\0') { 214 out->print_cr("No dump file specified"); 215 } else { 216 bool live_objects_only = true; // default is true to retain the behavior before this change is made 217 const char* arg1 = op->arg(1); 218 if (arg1 != NULL && (strlen(arg1) > 0)) { 219 if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) { 220 out->print_cr("Invalid argument to dumpheap operation: %s", arg1); 221 return JNI_ERR; 222 } 223 live_objects_only = strcmp(arg1, "-live") == 0; 224 } 225 226 // Request a full GC before heap dump if live_objects_only = true 227 // This helps reduces the amount of unreachable objects in the dump 228 // and makes it easier to browse. 229 HeapDumper dumper(live_objects_only /* request GC */); 230 int res = dumper.dump(op->arg(0)); 231 if (res == 0) { 232 out->print_cr("Heap dump file created"); 233 } else { 234 // heap dump failed 235 ResourceMark rm; 236 char* error = dumper.error_as_C_string(); 237 if (error == NULL) { 238 out->print_cr("Dump failed - reason unknown"); 239 } else { 240 out->print_cr("%s", error); 241 } 242 } 243 } 244 return JNI_OK; 245 } 246 247 // Implementation of "inspectheap" command 248 // See also: ClassHistogramDCmd class 249 // 250 // Input arguments :- 251 // arg0: "-live" or "-all" 252 static jint heap_inspection(AttachOperation* op, outputStream* out) { 253 bool live_objects_only = true; // default is true to retain the behavior before this change is made 254 const char* arg0 = op->arg(0); 255 if (arg0 != NULL && (strlen(arg0) > 0)) { 256 if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) { 257 out->print_cr("Invalid argument to inspectheap operation: %s", arg0); 258 return JNI_ERR; 259 } 260 live_objects_only = strcmp(arg0, "-live") == 0; 261 } 262 VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */); 263 VMThread::execute(&heapop); 264 return JNI_OK; 265 } 266 267 // Implementation of "setflag" command 268 static jint set_flag(AttachOperation* op, outputStream* out) { 269 270 const char* name = NULL; 271 if ((name = op->arg(0)) == NULL) { 272 out->print_cr("flag name is missing"); 273 return JNI_ERR; 274 } 275 276 FormatBuffer<80> err_msg("%s", ""); 277 278 int ret = WriteableFlags::set_flag(op->arg(0), op->arg(1), Flag::ATTACH_ON_DEMAND, err_msg); 279 if (ret != Flag::SUCCESS) { 280 if (ret == Flag::NON_WRITABLE) { 281 // if the flag is not manageable try to change it through 282 // the platform dependent implementation 283 return AttachListener::pd_set_flag(op, out); 284 } else { 285 out->print_cr("%s", err_msg.buffer()); 286 } 287 288 return JNI_ERR; 289 } 290 return JNI_OK; 291 } 292 293 // Implementation of "printflag" command 294 // See also: PrintVMFlagsDCmd class 295 static jint print_flag(AttachOperation* op, outputStream* out) { 296 const char* name = NULL; 297 if ((name = op->arg(0)) == NULL) { 298 out->print_cr("flag name is missing"); 299 return JNI_ERR; 300 } 301 Flag* f = Flag::find_flag((char*)name, strlen(name)); 302 if (f) { 303 f->print_as_flag(out); 304 out->cr(); 305 } else { 306 out->print_cr("no such flag '%s'", name); 307 } 308 return JNI_OK; 309 } 310 311 // Table to map operation names to functions. 312 313 // names must be of length <= AttachOperation::name_length_max 314 static AttachOperationFunctionInfo funcs[] = { 315 { "agentProperties", get_agent_properties }, 316 { "datadump", data_dump }, 317 { "dumpheap", dump_heap }, 318 { "load", load_agent }, 319 { "properties", get_system_properties }, 320 { "threaddump", thread_dump }, 321 { "inspectheap", heap_inspection }, 322 { "setflag", set_flag }, 323 { "printflag", print_flag }, 324 { "jcmd", jcmd }, 325 { NULL, NULL } 326 }; 327 328 329 330 // The Attach Listener threads services a queue. It dequeues an operation 331 // from the queue, examines the operation name (command), and dispatches 332 // to the corresponding function to perform the operation. 333 334 static void attach_listener_thread_entry(JavaThread* thread, TRAPS) { 335 os::set_priority(thread, NearMaxPriority); 336 337 assert(thread == Thread::current(), "Must be"); 338 assert(thread->stack_base() != NULL && thread->stack_size() > 0, 339 "Should already setup"); 340 341 if (AttachListener::pd_init() != 0) { 342 return; 343 } 344 AttachListener::set_initialized(); 345 346 for (;;) { 347 AttachOperation* op = AttachListener::dequeue(); 348 if (op == NULL) { 349 return; // dequeue failed or shutdown 350 } 351 352 ResourceMark rm; 353 bufferedStream st; 354 jint res = JNI_OK; 355 356 // handle special detachall operation 357 if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) { 358 AttachListener::detachall(); 359 } else if (!EnableDynamicAgentLoading && strcmp(op->name(), "load") == 0) { 360 st.print("Dynamic agent loading is not enabled. " 361 "Use -XX:+EnableDynamicAgentLoading to launch target VM."); 362 res = JNI_ERR; 363 } else { 364 // find the function to dispatch too 365 AttachOperationFunctionInfo* info = NULL; 366 for (int i=0; funcs[i].name != NULL; i++) { 367 const char* name = funcs[i].name; 368 assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max"); 369 if (strcmp(op->name(), name) == 0) { 370 info = &(funcs[i]); 371 break; 372 } 373 } 374 375 // check for platform dependent attach operation 376 if (info == NULL) { 377 info = AttachListener::pd_find_operation(op->name()); 378 } 379 380 if (info != NULL) { 381 // dispatch to the function that implements this operation 382 res = (info->func)(op, &st); 383 } else { 384 st.print("Operation %s not recognized!", op->name()); 385 res = JNI_ERR; 386 } 387 } 388 389 // operation complete - send result and output to client 390 op->complete(res, &st); 391 } 392 } 393 394 bool AttachListener::has_init_error(TRAPS) { 395 if (HAS_PENDING_EXCEPTION) { 396 tty->print_cr("Exception in VM (AttachListener::init) : "); 397 java_lang_Throwable::print(PENDING_EXCEPTION, tty); 398 tty->cr(); 399 400 CLEAR_PENDING_EXCEPTION; 401 402 return true; 403 } else { 404 return false; 405 } 406 } 407 408 // Starts the Attach Listener thread 409 void AttachListener::init() { 410 EXCEPTION_MARK; 411 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, THREAD); 412 if (has_init_error(THREAD)) { 413 return; 414 } 415 416 InstanceKlass* klass = InstanceKlass::cast(k); 417 instanceHandle thread_oop = klass->allocate_instance_handle(THREAD); 418 if (has_init_error(THREAD)) { 419 return; 420 } 421 422 const char thread_name[] = "Attach Listener"; 423 Handle string = java_lang_String::create_from_str(thread_name, THREAD); 424 if (has_init_error(THREAD)) { 425 return; 426 } 427 428 // Initialize thread_oop to put it into the system threadGroup 429 Handle thread_group (THREAD, Universe::system_thread_group()); 430 JavaValue result(T_VOID); 431 JavaCalls::call_special(&result, thread_oop, 432 klass, 433 vmSymbols::object_initializer_name(), 434 vmSymbols::threadgroup_string_void_signature(), 435 thread_group, 436 string, 437 THREAD); 438 439 if (has_init_error(THREAD)) { 440 return; 441 } 442 443 Klass* group = SystemDictionary::ThreadGroup_klass(); 444 JavaCalls::call_special(&result, 445 thread_group, 446 group, 447 vmSymbols::add_method_name(), 448 vmSymbols::thread_void_signature(), 449 thread_oop, // ARG 1 450 THREAD); 451 if (has_init_error(THREAD)) { 452 return; 453 } 454 455 { MutexLocker mu(Threads_lock); 456 JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry); 457 458 // Check that thread and osthread were created 459 if (listener_thread == NULL || listener_thread->osthread() == NULL) { 460 vm_exit_during_initialization("java.lang.OutOfMemoryError", 461 os::native_thread_creation_failed_msg()); 462 } 463 464 java_lang_Thread::set_thread(thread_oop(), listener_thread); 465 java_lang_Thread::set_daemon(thread_oop()); 466 467 listener_thread->set_threadObj(thread_oop()); 468 Threads::add(listener_thread); 469 Thread::start(listener_thread); 470 } 471 } 472 473 // Performs clean-up tasks on platforms where we can detect that the last 474 // client has detached 475 void AttachListener::detachall() { 476 // call the platform dependent clean-up 477 pd_detachall(); 478 }