1 /* 2 * Copyright (c) 2005, 2011, 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_implementation/shared/vmGCOperations.hpp" 29 #include "memory/resourceArea.hpp" 30 #include "prims/jvmtiExport.hpp" 31 #include "runtime/arguments.hpp" 32 #include "runtime/globals.hpp" 33 #include "runtime/java.hpp" 34 #include "runtime/javaCalls.hpp" 35 #include "runtime/os.hpp" 36 #include "services/attachListener.hpp" 37 #include "services/heapDumper.hpp" 38 #include "services/diagnosticCommand.hpp" 39 40 volatile bool AttachListener::_initialized; 41 42 // Implementation of "properties" command. 43 // 44 // Invokes sun.misc.VMSupport.serializePropertiesToByteArray to serialize 45 // the system properties into a byte array. 46 47 static klassOop load_and_initialize_klass(Symbol* sh, TRAPS) { 48 klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL); 49 instanceKlassHandle ik (THREAD, k); 50 if (ik->should_be_initialized()) { 51 ik->initialize(CHECK_NULL); 52 } 53 return ik(); 54 } 55 56 static jint get_properties(AttachOperation* op, outputStream* out, Symbol* serializePropertiesMethod) { 57 Thread* THREAD = Thread::current(); 58 HandleMark hm; 59 60 // load sun.misc.VMSupport 61 Symbol* klass = vmSymbols::sun_misc_VMSupport(); 62 klassOop k = load_and_initialize_klass(klass, THREAD); 63 if (HAS_PENDING_EXCEPTION) { 64 java_lang_Throwable::print(PENDING_EXCEPTION, out); 65 CLEAR_PENDING_EXCEPTION; 66 return JNI_ERR; 67 } 68 instanceKlassHandle ik(THREAD, k); 69 70 // invoke the serializePropertiesToByteArray method 71 JavaValue result(T_OBJECT); 72 JavaCallArguments args; 73 74 75 Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature(); 76 JavaCalls::call_static(&result, 77 ik, 78 serializePropertiesMethod, 79 signature, 80 &args, 81 THREAD); 82 if (HAS_PENDING_EXCEPTION) { 83 java_lang_Throwable::print(PENDING_EXCEPTION, out); 84 CLEAR_PENDING_EXCEPTION; 85 return JNI_ERR; 86 } 87 88 // The result should be a [B 89 oop res = (oop)result.get_jobject(); 90 assert(res->is_typeArray(), "just checking"); 91 assert(typeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking"); 92 93 // copy the bytes to the output stream 94 typeArrayOop ba = typeArrayOop(res); 95 jbyte* addr = typeArrayOop(res)->byte_at_addr(0); 96 out->print_raw((const char*)addr, ba->length()); 97 98 return JNI_OK; 99 } 100 101 // Implementation of "properties" command. 102 static jint get_system_properties(AttachOperation* op, outputStream* out) { 103 return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name()); 104 } 105 106 // Implementation of "agent_properties" command. 107 static jint get_agent_properties(AttachOperation* op, outputStream* out) { 108 return get_properties(op, out, vmSymbols::serializeAgentPropertiesToByteArray_name()); 109 } 110 111 // Implementation of "datadump" command. 112 // 113 // Raises a SIGBREAK signal so that VM dump threads, does deadlock detection, 114 // etc. In theory this command should only post a DataDumpRequest to any 115 // JVMTI environment that has enabled this event. However it's useful to 116 // trigger the SIGBREAK handler. 117 118 static jint data_dump(AttachOperation* op, outputStream* out) { 119 if (!ReduceSignalUsage) { 120 AttachListener::pd_data_dump(); 121 } else { 122 if (JvmtiExport::should_post_data_dump()) { 123 JvmtiExport::post_data_dump(); 124 } 125 } 126 return JNI_OK; 127 } 128 129 // Implementation of "threaddump" command - essentially a remote ctrl-break 130 // 131 static jint thread_dump(AttachOperation* op, outputStream* out) { 132 bool print_concurrent_locks = false; 133 if (op->arg(0) != NULL && strcmp(op->arg(0), "-l") == 0) { 134 print_concurrent_locks = true; 135 } 136 137 // thread stacks 138 VM_PrintThreads op1(out, print_concurrent_locks); 139 VMThread::execute(&op1); 140 141 // JNI global handles 142 VM_PrintJNI op2(out); 143 VMThread::execute(&op2); 144 145 // Deadlock detection 146 VM_FindDeadlocks op3(out); 147 VMThread::execute(&op3); 148 149 return JNI_OK; 150 } 151 152 /** 153 * A jcmd attach operation request was received, which will now 154 * dispatch to the diagnostic commands used for serviceability functions. 155 */ 156 static jint jcmd(AttachOperation* op, outputStream* out) { 157 Thread* THREAD = Thread::current(); 158 // All the supplied jcmd arguments are stored as a single 159 // string (op->arg(0)). This is parsed by the Dcmd framework. 160 DCmd::parse_and_execute(out, op->arg(0), ' ', THREAD); 161 if (HAS_PENDING_EXCEPTION) { 162 java_lang_Throwable::print(PENDING_EXCEPTION, out); 163 CLEAR_PENDING_EXCEPTION; 164 // The exception has been printed on the output stream 165 // If the JVM returns JNI_ERR, the attachAPI throws a generic I/O 166 // exception and the content of the output stream is not processed. 167 // By returning JNI_OK, the exception will be displayed on the client side 168 } 169 return JNI_OK; 170 } 171 172 #ifndef SERVICES_KERNEL // Heap dumping not supported 173 // Implementation of "dumpheap" command. 174 // 175 // Input arguments :- 176 // arg0: Name of the dump file 177 // arg1: "-live" or "-all" 178 jint dump_heap(AttachOperation* op, outputStream* out) { 179 const char* path = op->arg(0); 180 if (path == NULL || path[0] == '\0') { 181 out->print_cr("No dump file specified"); 182 } else { 183 bool live_objects_only = true; // default is true to retain the behavior before this change is made 184 const char* arg1 = op->arg(1); 185 if (arg1 != NULL && (strlen(arg1) > 0)) { 186 if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) { 187 out->print_cr("Invalid argument to dumpheap operation: %s", arg1); 188 return JNI_ERR; 189 } 190 live_objects_only = strcmp(arg1, "-live") == 0; 191 } 192 193 // Request a full GC before heap dump if live_objects_only = true 194 // This helps reduces the amount of unreachable objects in the dump 195 // and makes it easier to browse. 196 HeapDumper dumper(live_objects_only /* request GC */); 197 int res = dumper.dump(op->arg(0)); 198 if (res == 0) { 199 out->print_cr("Heap dump file created"); 200 } else { 201 // heap dump failed 202 ResourceMark rm; 203 char* error = dumper.error_as_C_string(); 204 if (error == NULL) { 205 out->print_cr("Dump failed - reason unknown"); 206 } else { 207 out->print_cr("%s", error); 208 } 209 } 210 } 211 return JNI_OK; 212 } 213 #endif // SERVICES_KERNEL 214 215 // Implementation of "inspectheap" command 216 // 217 // Input arguments :- 218 // arg0: "-live" or "-all" 219 static jint heap_inspection(AttachOperation* op, outputStream* out) { 220 bool live_objects_only = true; // default is true to retain the behavior before this change is made 221 const char* arg0 = op->arg(0); 222 if (arg0 != NULL && (strlen(arg0) > 0)) { 223 if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) { 224 out->print_cr("Invalid argument to inspectheap operation: %s", arg0); 225 return JNI_ERR; 226 } 227 live_objects_only = strcmp(arg0, "-live") == 0; 228 } 229 VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */, true /* need_prologue */); 230 VMThread::execute(&heapop); 231 return JNI_OK; 232 } 233 234 // set a boolean global flag using value from AttachOperation 235 static jint set_bool_flag(const char* name, AttachOperation* op, outputStream* out) { 236 bool value = true; 237 const char* arg1; 238 if ((arg1 = op->arg(1)) != NULL) { 239 int tmp; 240 int n = sscanf(arg1, "%d", &tmp); 241 if (n != 1) { 242 out->print_cr("flag value must be a boolean (1 or 0)"); 243 return JNI_ERR; 244 } 245 value = (tmp != 0); 246 } 247 bool res = CommandLineFlags::boolAtPut((char*)name, &value, ATTACH_ON_DEMAND); 248 if (! res) { 249 out->print_cr("setting flag %s failed", name); 250 } 251 return res? JNI_OK : JNI_ERR; 252 } 253 254 // set a intx global flag using value from AttachOperation 255 static jint set_intx_flag(const char* name, AttachOperation* op, outputStream* out) { 256 intx value; 257 const char* arg1; 258 if ((arg1 = op->arg(1)) != NULL) { 259 int n = sscanf(arg1, INTX_FORMAT, &value); 260 if (n != 1) { 261 out->print_cr("flag value must be an integer"); 262 return JNI_ERR; 263 } 264 } 265 bool res = CommandLineFlags::intxAtPut((char*)name, &value, ATTACH_ON_DEMAND); 266 if (! res) { 267 out->print_cr("setting flag %s failed", name); 268 } 269 270 return res? JNI_OK : JNI_ERR; 271 } 272 273 // set a uintx global flag using value from AttachOperation 274 static jint set_uintx_flag(const char* name, AttachOperation* op, outputStream* out) { 275 uintx value; 276 const char* arg1; 277 if ((arg1 = op->arg(1)) != NULL) { 278 int n = sscanf(arg1, UINTX_FORMAT, &value); 279 if (n != 1) { 280 out->print_cr("flag value must be an unsigned integer"); 281 return JNI_ERR; 282 } 283 } 284 bool res = CommandLineFlags::uintxAtPut((char*)name, &value, ATTACH_ON_DEMAND); 285 if (! res) { 286 out->print_cr("setting flag %s failed", name); 287 } 288 289 return res? JNI_OK : JNI_ERR; 290 } 291 292 // set a uint64_t global flag using value from AttachOperation 293 static jint set_uint64_t_flag(const char* name, AttachOperation* op, outputStream* out) { 294 uint64_t value; 295 const char* arg1; 296 if ((arg1 = op->arg(1)) != NULL) { 297 int n = sscanf(arg1, UINT64_FORMAT, &value); 298 if (n != 1) { 299 out->print_cr("flag value must be an unsigned 64-bit integer"); 300 return JNI_ERR; 301 } 302 } 303 bool res = CommandLineFlags::uint64_tAtPut((char*)name, &value, ATTACH_ON_DEMAND); 304 if (! res) { 305 out->print_cr("setting flag %s failed", name); 306 } 307 308 return res? JNI_OK : JNI_ERR; 309 } 310 311 // set a string global flag using value from AttachOperation 312 static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) { 313 const char* value; 314 if ((value = op->arg(1)) == NULL) { 315 out->print_cr("flag value must be a string"); 316 return JNI_ERR; 317 } 318 bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, ATTACH_ON_DEMAND); 319 if (res) { 320 FREE_C_HEAP_ARRAY(char, value); 321 } else { 322 out->print_cr("setting flag %s failed", name); 323 } 324 325 return res? JNI_OK : JNI_ERR; 326 } 327 328 // Implementation of "setflag" command 329 static jint set_flag(AttachOperation* op, outputStream* out) { 330 331 const char* name = NULL; 332 if ((name = op->arg(0)) == NULL) { 333 out->print_cr("flag name is missing"); 334 return JNI_ERR; 335 } 336 337 Flag* f = Flag::find_flag((char*)name, strlen(name)); 338 if (f && f->is_external() && f->is_writeable()) { 339 if (f->is_bool()) { 340 return set_bool_flag(name, op, out); 341 } else if (f->is_intx()) { 342 return set_intx_flag(name, op, out); 343 } else if (f->is_uintx()) { 344 return set_uintx_flag(name, op, out); 345 } else if (f->is_uint64_t()) { 346 return set_uint64_t_flag(name, op, out); 347 } else if (f->is_ccstr()) { 348 return set_ccstr_flag(name, op, out); 349 } else { 350 ShouldNotReachHere(); 351 return JNI_ERR; 352 } 353 } else { 354 return AttachListener::pd_set_flag(op, out); 355 } 356 } 357 358 // Implementation of "printflag" command 359 static jint print_flag(AttachOperation* op, outputStream* out) { 360 const char* name = NULL; 361 if ((name = op->arg(0)) == NULL) { 362 out->print_cr("flag name is missing"); 363 return JNI_ERR; 364 } 365 Flag* f = Flag::find_flag((char*)name, strlen(name)); 366 if (f) { 367 f->print_as_flag(out); 368 out->print_cr(""); 369 } else { 370 out->print_cr("no such flag '%s'", name); 371 } 372 return JNI_OK; 373 } 374 375 // Table to map operation names to functions. 376 377 // names must be of length <= AttachOperation::name_length_max 378 static AttachOperationFunctionInfo funcs[] = { 379 { "agentProperties", get_agent_properties }, 380 { "datadump", data_dump }, 381 #ifndef SERVICES_KERNEL 382 { "dumpheap", dump_heap }, 383 #endif // SERVICES_KERNEL 384 { "load", JvmtiExport::load_agent_library }, 385 { "properties", get_system_properties }, 386 { "threaddump", thread_dump }, 387 { "inspectheap", heap_inspection }, 388 { "setflag", set_flag }, 389 { "printflag", print_flag }, 390 { "jcmd", jcmd }, 391 { NULL, NULL } 392 }; 393 394 395 396 // The Attach Listener threads services a queue. It dequeues an operation 397 // from the queue, examines the operation name (command), and dispatches 398 // to the corresponding function to perform the operation. 399 400 static void attach_listener_thread_entry(JavaThread* thread, TRAPS) { 401 os::set_priority(thread, NearMaxPriority); 402 403 if (AttachListener::pd_init() != 0) { 404 return; 405 } 406 AttachListener::set_initialized(); 407 408 for (;;) { 409 AttachOperation* op = AttachListener::dequeue(); 410 if (op == NULL) { 411 return; // dequeue failed or shutdown 412 } 413 414 ResourceMark rm; 415 bufferedStream st; 416 jint res = JNI_OK; 417 418 // handle special detachall operation 419 if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) { 420 AttachListener::detachall(); 421 } else { 422 // find the function to dispatch too 423 AttachOperationFunctionInfo* info = NULL; 424 for (int i=0; funcs[i].name != NULL; i++) { 425 const char* name = funcs[i].name; 426 assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max"); 427 if (strcmp(op->name(), name) == 0) { 428 info = &(funcs[i]); 429 break; 430 } 431 } 432 433 // check for platform dependent attach operation 434 if (info == NULL) { 435 info = AttachListener::pd_find_operation(op->name()); 436 } 437 438 if (info != NULL) { 439 // dispatch to the function that implements this operation 440 res = (info->func)(op, &st); 441 } else { 442 st.print("Operation %s not recognized!", op->name()); 443 res = JNI_ERR; 444 } 445 } 446 447 // operation complete - send result and output to client 448 op->complete(res, &st); 449 } 450 } 451 452 // Starts the Attach Listener thread 453 void AttachListener::init() { 454 EXCEPTION_MARK; 455 klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK); 456 instanceKlassHandle klass (THREAD, k); 457 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); 458 459 const char thread_name[] = "Attach Listener"; 460 Handle string = java_lang_String::create_from_str(thread_name, CHECK); 461 462 // Initialize thread_oop to put it into the system threadGroup 463 Handle thread_group (THREAD, Universe::system_thread_group()); 464 JavaValue result(T_VOID); 465 JavaCalls::call_special(&result, thread_oop, 466 klass, 467 vmSymbols::object_initializer_name(), 468 vmSymbols::threadgroup_string_void_signature(), 469 thread_group, 470 string, 471 CHECK); 472 473 KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); 474 JavaCalls::call_special(&result, 475 thread_group, 476 group, 477 vmSymbols::add_method_name(), 478 vmSymbols::thread_void_signature(), 479 thread_oop, // ARG 1 480 CHECK); 481 482 { MutexLocker mu(Threads_lock); 483 JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry); 484 485 // Check that thread and osthread were created 486 if (listener_thread == NULL || listener_thread->osthread() == NULL) { 487 vm_exit_during_initialization("java.lang.OutOfMemoryError", 488 "unable to create new native thread"); 489 } 490 491 java_lang_Thread::set_thread(thread_oop(), listener_thread); 492 java_lang_Thread::set_daemon(thread_oop()); 493 494 listener_thread->set_threadObj(thread_oop()); 495 Threads::add(listener_thread); 496 Thread::start(listener_thread); 497 } 498 } 499 500 // Performs clean-up tasks on platforms where we can detect that the last 501 // client has detached 502 void AttachListener::detachall() { 503 // call the platform dependent clean-up 504 pd_detachall(); 505 }