1.1 --- a/src/share/vm/services/diagnosticFramework.cpp Wed May 01 09:00:39 2013 -0700 1.2 +++ b/src/share/vm/services/diagnosticFramework.cpp Fri May 03 05:05:31 2013 -0700 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -359,7 +359,7 @@ 1.11 while (arg != NULL) { 1.12 array->append(new DCmdArgumentInfo(arg->name(), arg->description(), 1.13 arg->type(), arg->default_string(), arg->is_mandatory(), 1.14 - false, idx)); 1.15 + false, arg->allow_multiple(), idx)); 1.16 idx++; 1.17 arg = arg->next(); 1.18 } 1.19 @@ -367,32 +367,42 @@ 1.20 while (arg != NULL) { 1.21 array->append(new DCmdArgumentInfo(arg->name(), arg->description(), 1.22 arg->type(), arg->default_string(), arg->is_mandatory(), 1.23 - true)); 1.24 + true, arg->allow_multiple())); 1.25 arg = arg->next(); 1.26 } 1.27 return array; 1.28 } 1.29 1.30 DCmdFactory* DCmdFactory::_DCmdFactoryList = NULL; 1.31 +bool DCmdFactory::_has_pending_jmx_notification = false; 1.32 1.33 -void DCmd::parse_and_execute(outputStream* out, const char* cmdline, 1.34 - char delim, TRAPS) { 1.35 +void DCmd::parse_and_execute(DCmdSource source, outputStream* out, 1.36 + const char* cmdline, char delim, TRAPS) { 1.37 1.38 if (cmdline == NULL) return; // Nothing to do! 1.39 DCmdIter iter(cmdline, '\n'); 1.40 1.41 + int count = 0; 1.42 while (iter.has_next()) { 1.43 + if(source == DCmd_Source_MBean && count > 0) { 1.44 + // When diagnostic commands are invoked via JMX, each command line 1.45 + // must contains one and only one command because of the Permission 1.46 + // checks performed by the DiagnosticCommandMBean 1.47 + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 1.48 + "Invalid syntax"); 1.49 + } 1.50 CmdLine line = iter.next(); 1.51 if (line.is_stop()) { 1.52 break; 1.53 } 1.54 if (line.is_executable()) { 1.55 - DCmd* command = DCmdFactory::create_local_DCmd(line, out, CHECK); 1.56 + DCmd* command = DCmdFactory::create_local_DCmd(source, line, out, CHECK); 1.57 assert(command != NULL, "command error must be handled before this line"); 1.58 DCmdMark mark(command); 1.59 command->parse(&line, delim, CHECK); 1.60 - command->execute(CHECK); 1.61 + command->execute(source, CHECK); 1.62 } 1.63 + count++; 1.64 } 1.65 } 1.66 1.67 @@ -420,15 +430,78 @@ 1.68 return _dcmdparser.argument_info_array(); 1.69 } 1.70 1.71 +void DCmdFactory::push_jmx_notification_request() { 1.72 + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); 1.73 + _has_pending_jmx_notification = true; 1.74 + Service_lock->notify_all(); 1.75 +} 1.76 + 1.77 +void DCmdFactory::send_notification(TRAPS) { 1.78 + DCmdFactory::send_notification_internal(THREAD); 1.79 + // Clearing pending exception to avoid premature termination of 1.80 + // the service thread 1.81 + if (HAS_PENDING_EXCEPTION) { 1.82 + CLEAR_PENDING_EXCEPTION; 1.83 + } 1.84 +} 1.85 +void DCmdFactory::send_notification_internal(TRAPS) { 1.86 + ResourceMark rm(THREAD); 1.87 + HandleMark hm(THREAD); 1.88 + bool notif = false; 1.89 + { 1.90 + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); 1.91 + notif = _has_pending_jmx_notification; 1.92 + _has_pending_jmx_notification = false; 1.93 + } 1.94 + if (notif) { 1.95 + 1.96 + Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK); 1.97 + instanceKlassHandle mgmt_factory_helper_klass(THREAD, k); 1.98 + 1.99 + JavaValue result(T_OBJECT); 1.100 + JavaCalls::call_static(&result, 1.101 + mgmt_factory_helper_klass, 1.102 + vmSymbols::getDiagnosticCommandMBean_name(), 1.103 + vmSymbols::getDiagnosticCommandMBean_signature(), 1.104 + CHECK); 1.105 + 1.106 + instanceOop m = (instanceOop) result.get_jobject(); 1.107 + instanceHandle dcmd_mbean_h(THREAD, m); 1.108 + 1.109 + Klass* k2 = Management::sun_management_DiagnosticCommandImpl_klass(CHECK); 1.110 + instanceKlassHandle dcmd_mbean_klass(THREAD, k2); 1.111 + 1.112 + if (!dcmd_mbean_h->is_a(k2)) { 1.113 + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 1.114 + "ManagementFactory.getDiagnosticCommandMBean didn't return a DiagnosticCommandMBean instance"); 1.115 + } 1.116 + 1.117 + JavaValue result2(T_VOID); 1.118 + JavaCallArguments args2(dcmd_mbean_h); 1.119 + 1.120 + JavaCalls::call_virtual(&result2, 1.121 + dcmd_mbean_klass, 1.122 + vmSymbols::createDiagnosticFrameworkNotification_name(), 1.123 + vmSymbols::void_method_signature(), 1.124 + &args2, 1.125 + CHECK); 1.126 + } 1.127 +} 1.128 + 1.129 Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true); 1.130 +bool DCmdFactory::_send_jmx_notification = false; 1.131 1.132 -DCmdFactory* DCmdFactory::factory(const char* name, size_t len) { 1.133 +DCmdFactory* DCmdFactory::factory(DCmdSource source, const char* name, size_t len) { 1.134 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 1.135 DCmdFactory* factory = _DCmdFactoryList; 1.136 while (factory != NULL) { 1.137 if (strlen(factory->name()) == len && 1.138 strncmp(name, factory->name(), len) == 0) { 1.139 - return factory; 1.140 + if(factory->export_flags() & source) { 1.141 + return factory; 1.142 + } else { 1.143 + return NULL; 1.144 + } 1.145 } 1.146 factory = factory->_next; 1.147 } 1.148 @@ -439,11 +512,16 @@ 1.149 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 1.150 factory->_next = _DCmdFactoryList; 1.151 _DCmdFactoryList = factory; 1.152 + if (_send_jmx_notification && !factory->_hidden 1.153 + && (factory->_export_flags & DCmd_Source_MBean)) { 1.154 + DCmdFactory::push_jmx_notification_request(); 1.155 + } 1.156 return 0; // Actually, there's no checks for duplicates 1.157 } 1.158 1.159 -DCmd* DCmdFactory::create_global_DCmd(CmdLine &line, outputStream* out, TRAPS) { 1.160 - DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len()); 1.161 +DCmd* DCmdFactory::create_global_DCmd(DCmdSource source, CmdLine &line, 1.162 + outputStream* out, TRAPS) { 1.163 + DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len()); 1.164 if (f != NULL) { 1.165 if (f->is_enabled()) { 1.166 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), 1.167 @@ -455,8 +533,9 @@ 1.168 "Unknown diagnostic command"); 1.169 } 1.170 1.171 -DCmd* DCmdFactory::create_local_DCmd(CmdLine &line, outputStream* out, TRAPS) { 1.172 - DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len()); 1.173 +DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line, 1.174 + outputStream* out, TRAPS) { 1.175 + DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len()); 1.176 if (f != NULL) { 1.177 if (!f->is_enabled()) { 1.178 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), 1.179 @@ -468,12 +547,12 @@ 1.180 "Unknown diagnostic command"); 1.181 } 1.182 1.183 -GrowableArray<const char*>* DCmdFactory::DCmd_list() { 1.184 +GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) { 1.185 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 1.186 GrowableArray<const char*>* array = new GrowableArray<const char*>(); 1.187 DCmdFactory* factory = _DCmdFactoryList; 1.188 while (factory != NULL) { 1.189 - if (!factory->is_hidden()) { 1.190 + if (!factory->is_hidden() && (factory->export_flags() & source)) { 1.191 array->append(factory->name()); 1.192 } 1.193 factory = factory->next(); 1.194 @@ -481,15 +560,16 @@ 1.195 return array; 1.196 } 1.197 1.198 -GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list() { 1.199 +GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list(DCmdSource source ) { 1.200 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); 1.201 GrowableArray<DCmdInfo*>* array = new GrowableArray<DCmdInfo*>(); 1.202 DCmdFactory* factory = _DCmdFactoryList; 1.203 while (factory != NULL) { 1.204 - if (!factory->is_hidden()) { 1.205 + if (!factory->is_hidden() && (factory->export_flags() & source)) { 1.206 array->append(new DCmdInfo(factory->name(), 1.207 factory->description(), factory->impact(), 1.208 - factory->num_arguments(), factory->is_enabled())); 1.209 + factory->permission(), factory->num_arguments(), 1.210 + factory->is_enabled())); 1.211 } 1.212 factory = factory->next(); 1.213 }