1 /* 2 * Copyright (c) 2003, 2012, 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 "prims/jvmtiExport.hpp" 27 #include "prims/jvmtiExtensions.hpp" 28 29 // the list of extension functions 30 GrowableArray<jvmtiExtensionFunctionInfo*>* JvmtiExtensions::_ext_functions; 31 32 // the list of extension events 33 GrowableArray<jvmtiExtensionEventInfo*>* JvmtiExtensions::_ext_events; 34 35 36 // extension function 37 static jvmtiError JNICALL IsClassUnloadingEnabled(const jvmtiEnv* env, jboolean* enabled, ...) { 38 if (enabled == NULL) { 39 return JVMTI_ERROR_NULL_POINTER; 40 } 41 *enabled = (jboolean)ClassUnloading; 42 return JVMTI_ERROR_NONE; 43 } 44 45 // register extension functions and events. In this implementation we 46 // have a single extension function (to prove the API) that tests if class 47 // unloading is enabled or disabled. We also have a single extension event 48 // EXT_EVENT_CLASS_UNLOAD which is used to provide the JVMDI_EVENT_CLASS_UNLOAD 49 // event. The function and the event are registered here. 50 // 51 void JvmtiExtensions::register_extensions() { 52 _ext_functions = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiExtensionFunctionInfo*>(1,true); 53 _ext_events = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiExtensionEventInfo*>(1,true); 54 55 // register our extension function 56 static jvmtiParamInfo func_params[] = { 57 { (char*)"IsClassUnloadingEnabled", JVMTI_KIND_OUT, JVMTI_TYPE_JBOOLEAN, JNI_FALSE } 58 }; 59 static jvmtiExtensionFunctionInfo ext_func = { 60 (jvmtiExtensionFunction)IsClassUnloadingEnabled, 61 (char*)"com.sun.hotspot.functions.IsClassUnloadingEnabled", 62 (char*)"Tell if class unloading is enabled (-noclassgc)", 63 sizeof(func_params)/sizeof(func_params[0]), 64 func_params, 65 0, // no non-universal errors 66 NULL 67 }; 68 _ext_functions->append(&ext_func); 69 70 // register our extension event 71 72 static jvmtiParamInfo event_params[] = { 73 { (char*)"JNI Environment", JVMTI_KIND_IN_PTR, JVMTI_TYPE_JNIENV, JNI_FALSE }, 74 { (char*)"Class", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CCHAR, JNI_FALSE } 75 }; 76 static jvmtiExtensionEventInfo ext_event = { 77 EXT_EVENT_CLASS_UNLOAD, 78 (char*)"com.sun.hotspot.events.ClassUnload", 79 (char*)"CLASS_UNLOAD event", 80 sizeof(event_params)/sizeof(event_params[0]), 81 event_params 82 }; 83 _ext_events->append(&ext_event); 84 } 85 86 87 // return the list of extension functions 88 89 jvmtiError JvmtiExtensions::get_functions(JvmtiEnv* env, 90 jint* extension_count_ptr, 91 jvmtiExtensionFunctionInfo** extensions) 92 { 93 guarantee(_ext_functions != NULL, "registration not done"); 94 95 ResourceTracker rt(env); 96 97 jvmtiExtensionFunctionInfo* ext_funcs; 98 jvmtiError err = rt.allocate(_ext_functions->length() * 99 sizeof(jvmtiExtensionFunctionInfo), 100 (unsigned char**)&ext_funcs); 101 if (err != JVMTI_ERROR_NONE) { 102 return err; 103 } 104 105 for (int i=0; i<_ext_functions->length(); i++ ) { 106 ext_funcs[i].func = _ext_functions->at(i)->func; 107 108 char *id = _ext_functions->at(i)->id; 109 err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_funcs[i].id)); 110 if (err != JVMTI_ERROR_NONE) { 111 return err; 112 } 113 strcpy(ext_funcs[i].id, id); 114 115 char *desc = _ext_functions->at(i)->short_description; 116 err = rt.allocate(strlen(desc)+1, 117 (unsigned char**)&(ext_funcs[i].short_description)); 118 if (err != JVMTI_ERROR_NONE) { 119 return err; 120 } 121 strcpy(ext_funcs[i].short_description, desc); 122 123 // params 124 125 jint param_count = _ext_functions->at(i)->param_count; 126 127 ext_funcs[i].param_count = param_count; 128 if (param_count == 0) { 129 ext_funcs[i].params = NULL; 130 } else { 131 err = rt.allocate(param_count*sizeof(jvmtiParamInfo), 132 (unsigned char**)&(ext_funcs[i].params)); 133 if (err != JVMTI_ERROR_NONE) { 134 return err; 135 } 136 jvmtiParamInfo* src_params = _ext_functions->at(i)->params; 137 jvmtiParamInfo* dst_params = ext_funcs[i].params; 138 139 for (int j=0; j<param_count; j++) { 140 err = rt.allocate(strlen(src_params[j].name)+1, 141 (unsigned char**)&(dst_params[j].name)); 142 if (err != JVMTI_ERROR_NONE) { 143 return err; 144 } 145 strcpy(dst_params[j].name, src_params[j].name); 146 147 dst_params[j].kind = src_params[j].kind; 148 dst_params[j].base_type = src_params[j].base_type; 149 dst_params[j].null_ok = src_params[j].null_ok; 150 } 151 } 152 153 // errors 154 155 jint error_count = _ext_functions->at(i)->error_count; 156 ext_funcs[i].error_count = error_count; 157 if (error_count == 0) { 158 ext_funcs[i].errors = NULL; 159 } else { 160 err = rt.allocate(error_count*sizeof(jvmtiError), 161 (unsigned char**)&(ext_funcs[i].errors)); 162 if (err != JVMTI_ERROR_NONE) { 163 return err; 164 } 165 memcpy(ext_funcs[i].errors, _ext_functions->at(i)->errors, 166 error_count*sizeof(jvmtiError)); 167 } 168 } 169 170 *extension_count_ptr = _ext_functions->length(); 171 *extensions = ext_funcs; 172 return JVMTI_ERROR_NONE; 173 } 174 175 176 // return the list of extension events 177 178 jvmtiError JvmtiExtensions::get_events(JvmtiEnv* env, 179 jint* extension_count_ptr, 180 jvmtiExtensionEventInfo** extensions) 181 { 182 guarantee(_ext_events != NULL, "registration not done"); 183 184 ResourceTracker rt(env); 185 186 jvmtiExtensionEventInfo* ext_events; 187 jvmtiError err = rt.allocate(_ext_events->length() * sizeof(jvmtiExtensionEventInfo), 188 (unsigned char**)&ext_events); 189 if (err != JVMTI_ERROR_NONE) { 190 return err; 191 } 192 193 for (int i=0; i<_ext_events->length(); i++ ) { 194 ext_events[i].extension_event_index = _ext_events->at(i)->extension_event_index; 195 196 char *id = _ext_events->at(i)->id; 197 err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_events[i].id)); 198 if (err != JVMTI_ERROR_NONE) { 199 return err; 200 } 201 strcpy(ext_events[i].id, id); 202 203 char *desc = _ext_events->at(i)->short_description; 204 err = rt.allocate(strlen(desc)+1, 205 (unsigned char**)&(ext_events[i].short_description)); 206 if (err != JVMTI_ERROR_NONE) { 207 return err; 208 } 209 strcpy(ext_events[i].short_description, desc); 210 211 // params 212 213 jint param_count = _ext_events->at(i)->param_count; 214 215 ext_events[i].param_count = param_count; 216 if (param_count == 0) { 217 ext_events[i].params = NULL; 218 } else { 219 err = rt.allocate(param_count*sizeof(jvmtiParamInfo), 220 (unsigned char**)&(ext_events[i].params)); 221 if (err != JVMTI_ERROR_NONE) { 222 return err; 223 } 224 jvmtiParamInfo* src_params = _ext_events->at(i)->params; 225 jvmtiParamInfo* dst_params = ext_events[i].params; 226 227 for (int j=0; j<param_count; j++) { 228 err = rt.allocate(strlen(src_params[j].name)+1, 229 (unsigned char**)&(dst_params[j].name)); 230 if (err != JVMTI_ERROR_NONE) { 231 return err; 232 } 233 strcpy(dst_params[j].name, src_params[j].name); 234 235 dst_params[j].kind = src_params[j].kind; 236 dst_params[j].base_type = src_params[j].base_type; 237 dst_params[j].null_ok = src_params[j].null_ok; 238 } 239 } 240 } 241 242 *extension_count_ptr = _ext_events->length(); 243 *extensions = ext_events; 244 return JVMTI_ERROR_NONE; 245 } 246 247 // set callback for an extension event and enable/disable it. 248 249 jvmtiError JvmtiExtensions::set_event_callback(JvmtiEnv* env, 250 jint extension_event_index, 251 jvmtiExtensionEvent callback) 252 { 253 guarantee(_ext_events != NULL, "registration not done"); 254 255 jvmtiExtensionEventInfo* event = NULL; 256 257 // if there are extension events registered then validate that the 258 // extension_event_index matches one of the registered events. 259 if (_ext_events != NULL) { 260 for (int i=0; i<_ext_events->length(); i++ ) { 261 if (_ext_events->at(i)->extension_event_index == extension_event_index) { 262 event = _ext_events->at(i); 263 break; 264 } 265 } 266 } 267 268 // invalid event index 269 if (event == NULL) { 270 return JVMTI_ERROR_ILLEGAL_ARGUMENT; 271 } 272 273 JvmtiEventController::set_extension_event_callback(env, extension_event_index, 274 callback); 275 276 return JVMTI_ERROR_NONE; 277 }