comparison src/share/vm/services/diagnosticFramework.cpp @ 10215:31a4e55f8c9d

8004095: Add support for JMX interface to Diagnostic Framework and Commands Reviewed-by: acorn, sla
author fparain
date Fri, 03 May 2013 05:05:31 -0700
parents 5a1f452f8f90
children 78bbf4d43a14
comparison
equal deleted inserted replaced
10167:8fe2542bdc8d 10215:31a4e55f8c9d
1 /* 1 /*
2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
357 int idx = 0; 357 int idx = 0;
358 GenDCmdArgument* arg = _arguments_list; 358 GenDCmdArgument* arg = _arguments_list;
359 while (arg != NULL) { 359 while (arg != NULL) {
360 array->append(new DCmdArgumentInfo(arg->name(), arg->description(), 360 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
361 arg->type(), arg->default_string(), arg->is_mandatory(), 361 arg->type(), arg->default_string(), arg->is_mandatory(),
362 false, idx)); 362 false, arg->allow_multiple(), idx));
363 idx++; 363 idx++;
364 arg = arg->next(); 364 arg = arg->next();
365 } 365 }
366 arg = _options; 366 arg = _options;
367 while (arg != NULL) { 367 while (arg != NULL) {
368 array->append(new DCmdArgumentInfo(arg->name(), arg->description(), 368 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
369 arg->type(), arg->default_string(), arg->is_mandatory(), 369 arg->type(), arg->default_string(), arg->is_mandatory(),
370 true)); 370 true, arg->allow_multiple()));
371 arg = arg->next(); 371 arg = arg->next();
372 } 372 }
373 return array; 373 return array;
374 } 374 }
375 375
376 DCmdFactory* DCmdFactory::_DCmdFactoryList = NULL; 376 DCmdFactory* DCmdFactory::_DCmdFactoryList = NULL;
377 377 bool DCmdFactory::_has_pending_jmx_notification = false;
378 void DCmd::parse_and_execute(outputStream* out, const char* cmdline, 378
379 char delim, TRAPS) { 379 void DCmd::parse_and_execute(DCmdSource source, outputStream* out,
380 const char* cmdline, char delim, TRAPS) {
380 381
381 if (cmdline == NULL) return; // Nothing to do! 382 if (cmdline == NULL) return; // Nothing to do!
382 DCmdIter iter(cmdline, '\n'); 383 DCmdIter iter(cmdline, '\n');
383 384
385 int count = 0;
384 while (iter.has_next()) { 386 while (iter.has_next()) {
387 if(source == DCmd_Source_MBean && count > 0) {
388 // When diagnostic commands are invoked via JMX, each command line
389 // must contains one and only one command because of the Permission
390 // checks performed by the DiagnosticCommandMBean
391 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
392 "Invalid syntax");
393 }
385 CmdLine line = iter.next(); 394 CmdLine line = iter.next();
386 if (line.is_stop()) { 395 if (line.is_stop()) {
387 break; 396 break;
388 } 397 }
389 if (line.is_executable()) { 398 if (line.is_executable()) {
390 DCmd* command = DCmdFactory::create_local_DCmd(line, out, CHECK); 399 DCmd* command = DCmdFactory::create_local_DCmd(source, line, out, CHECK);
391 assert(command != NULL, "command error must be handled before this line"); 400 assert(command != NULL, "command error must be handled before this line");
392 DCmdMark mark(command); 401 DCmdMark mark(command);
393 command->parse(&line, delim, CHECK); 402 command->parse(&line, delim, CHECK);
394 command->execute(CHECK); 403 command->execute(source, CHECK);
395 } 404 }
405 count++;
396 } 406 }
397 } 407 }
398 408
399 void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) { 409 void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) {
400 _dcmdparser.parse(line, delim, CHECK); 410 _dcmdparser.parse(line, delim, CHECK);
418 428
419 GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() { 429 GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() {
420 return _dcmdparser.argument_info_array(); 430 return _dcmdparser.argument_info_array();
421 } 431 }
422 432
433 void DCmdFactory::push_jmx_notification_request() {
434 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
435 _has_pending_jmx_notification = true;
436 Service_lock->notify_all();
437 }
438
439 void DCmdFactory::send_notification(TRAPS) {
440 DCmdFactory::send_notification_internal(THREAD);
441 // Clearing pending exception to avoid premature termination of
442 // the service thread
443 if (HAS_PENDING_EXCEPTION) {
444 CLEAR_PENDING_EXCEPTION;
445 }
446 }
447 void DCmdFactory::send_notification_internal(TRAPS) {
448 ResourceMark rm(THREAD);
449 HandleMark hm(THREAD);
450 bool notif = false;
451 {
452 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
453 notif = _has_pending_jmx_notification;
454 _has_pending_jmx_notification = false;
455 }
456 if (notif) {
457
458 Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK);
459 instanceKlassHandle mgmt_factory_helper_klass(THREAD, k);
460
461 JavaValue result(T_OBJECT);
462 JavaCalls::call_static(&result,
463 mgmt_factory_helper_klass,
464 vmSymbols::getDiagnosticCommandMBean_name(),
465 vmSymbols::getDiagnosticCommandMBean_signature(),
466 CHECK);
467
468 instanceOop m = (instanceOop) result.get_jobject();
469 instanceHandle dcmd_mbean_h(THREAD, m);
470
471 Klass* k2 = Management::sun_management_DiagnosticCommandImpl_klass(CHECK);
472 instanceKlassHandle dcmd_mbean_klass(THREAD, k2);
473
474 if (!dcmd_mbean_h->is_a(k2)) {
475 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
476 "ManagementFactory.getDiagnosticCommandMBean didn't return a DiagnosticCommandMBean instance");
477 }
478
479 JavaValue result2(T_VOID);
480 JavaCallArguments args2(dcmd_mbean_h);
481
482 JavaCalls::call_virtual(&result2,
483 dcmd_mbean_klass,
484 vmSymbols::createDiagnosticFrameworkNotification_name(),
485 vmSymbols::void_method_signature(),
486 &args2,
487 CHECK);
488 }
489 }
490
423 Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true); 491 Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true);
424 492 bool DCmdFactory::_send_jmx_notification = false;
425 DCmdFactory* DCmdFactory::factory(const char* name, size_t len) { 493
494 DCmdFactory* DCmdFactory::factory(DCmdSource source, const char* name, size_t len) {
426 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 495 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
427 DCmdFactory* factory = _DCmdFactoryList; 496 DCmdFactory* factory = _DCmdFactoryList;
428 while (factory != NULL) { 497 while (factory != NULL) {
429 if (strlen(factory->name()) == len && 498 if (strlen(factory->name()) == len &&
430 strncmp(name, factory->name(), len) == 0) { 499 strncmp(name, factory->name(), len) == 0) {
431 return factory; 500 if(factory->export_flags() & source) {
501 return factory;
502 } else {
503 return NULL;
504 }
432 } 505 }
433 factory = factory->_next; 506 factory = factory->_next;
434 } 507 }
435 return NULL; 508 return NULL;
436 } 509 }
437 510
438 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) { 511 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) {
439 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 512 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
440 factory->_next = _DCmdFactoryList; 513 factory->_next = _DCmdFactoryList;
441 _DCmdFactoryList = factory; 514 _DCmdFactoryList = factory;
515 if (_send_jmx_notification && !factory->_hidden
516 && (factory->_export_flags & DCmd_Source_MBean)) {
517 DCmdFactory::push_jmx_notification_request();
518 }
442 return 0; // Actually, there's no checks for duplicates 519 return 0; // Actually, there's no checks for duplicates
443 } 520 }
444 521
445 DCmd* DCmdFactory::create_global_DCmd(CmdLine &line, outputStream* out, TRAPS) { 522 DCmd* DCmdFactory::create_global_DCmd(DCmdSource source, CmdLine &line,
446 DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len()); 523 outputStream* out, TRAPS) {
524 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
447 if (f != NULL) { 525 if (f != NULL) {
448 if (f->is_enabled()) { 526 if (f->is_enabled()) {
449 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), 527 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
450 f->disabled_message()); 528 f->disabled_message());
451 } 529 }
453 } 531 }
454 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), 532 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
455 "Unknown diagnostic command"); 533 "Unknown diagnostic command");
456 } 534 }
457 535
458 DCmd* DCmdFactory::create_local_DCmd(CmdLine &line, outputStream* out, TRAPS) { 536 DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line,
459 DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len()); 537 outputStream* out, TRAPS) {
538 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
460 if (f != NULL) { 539 if (f != NULL) {
461 if (!f->is_enabled()) { 540 if (!f->is_enabled()) {
462 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), 541 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
463 f->disabled_message()); 542 f->disabled_message());
464 } 543 }
466 } 545 }
467 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), 546 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
468 "Unknown diagnostic command"); 547 "Unknown diagnostic command");
469 } 548 }
470 549
471 GrowableArray<const char*>* DCmdFactory::DCmd_list() { 550 GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) {
472 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 551 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
473 GrowableArray<const char*>* array = new GrowableArray<const char*>(); 552 GrowableArray<const char*>* array = new GrowableArray<const char*>();
474 DCmdFactory* factory = _DCmdFactoryList; 553 DCmdFactory* factory = _DCmdFactoryList;
475 while (factory != NULL) { 554 while (factory != NULL) {
476 if (!factory->is_hidden()) { 555 if (!factory->is_hidden() && (factory->export_flags() & source)) {
477 array->append(factory->name()); 556 array->append(factory->name());
478 } 557 }
479 factory = factory->next(); 558 factory = factory->next();
480 } 559 }
481 return array; 560 return array;
482 } 561 }
483 562
484 GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list() { 563 GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list(DCmdSource source ) {
485 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 564 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
486 GrowableArray<DCmdInfo*>* array = new GrowableArray<DCmdInfo*>(); 565 GrowableArray<DCmdInfo*>* array = new GrowableArray<DCmdInfo*>();
487 DCmdFactory* factory = _DCmdFactoryList; 566 DCmdFactory* factory = _DCmdFactoryList;
488 while (factory != NULL) { 567 while (factory != NULL) {
489 if (!factory->is_hidden()) { 568 if (!factory->is_hidden() && (factory->export_flags() & source)) {
490 array->append(new DCmdInfo(factory->name(), 569 array->append(new DCmdInfo(factory->name(),
491 factory->description(), factory->impact(), 570 factory->description(), factory->impact(),
492 factory->num_arguments(), factory->is_enabled())); 571 factory->permission(), factory->num_arguments(),
572 factory->is_enabled()));
493 } 573 }
494 factory = factory->next(); 574 factory = factory->next();
495 } 575 }
496 return array; 576 return array;
497 } 577 }