duke@435: /* mikael@4153: * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "prims/jvmtiExport.hpp" stefank@2314: #include "prims/jvmtiExtensions.hpp" duke@435: duke@435: // the list of extension functions duke@435: GrowableArray* JvmtiExtensions::_ext_functions; duke@435: duke@435: // the list of extension events duke@435: GrowableArray* JvmtiExtensions::_ext_events; duke@435: duke@435: duke@435: // extension function duke@435: static jvmtiError JNICALL IsClassUnloadingEnabled(const jvmtiEnv* env, jboolean* enabled, ...) { duke@435: if (enabled == NULL) { duke@435: return JVMTI_ERROR_NULL_POINTER; duke@435: } duke@435: *enabled = (jboolean)ClassUnloading; duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: duke@435: // register extension functions and events. In this implementation we duke@435: // have a single extension function (to prove the API) that tests if class duke@435: // unloading is enabled or disabled. We also have a single extension event duke@435: // EXT_EVENT_CLASS_UNLOAD which is used to provide the JVMDI_EVENT_CLASS_UNLOAD duke@435: // event. The function and the event are registered here. duke@435: // duke@435: void JvmtiExtensions::register_extensions() { zgu@3900: _ext_functions = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(1,true); zgu@3900: _ext_events = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(1,true); duke@435: duke@435: // register our extension function duke@435: static jvmtiParamInfo func_params[] = { duke@435: { (char*)"IsClassUnloadingEnabled", JVMTI_KIND_OUT, JVMTI_TYPE_JBOOLEAN, JNI_FALSE } duke@435: }; duke@435: static jvmtiExtensionFunctionInfo ext_func = { duke@435: (jvmtiExtensionFunction)IsClassUnloadingEnabled, duke@435: (char*)"com.sun.hotspot.functions.IsClassUnloadingEnabled", duke@435: (char*)"Tell if class unloading is enabled (-noclassgc)", duke@435: sizeof(func_params)/sizeof(func_params[0]), duke@435: func_params, duke@435: 0, // no non-universal errors duke@435: NULL duke@435: }; duke@435: _ext_functions->append(&ext_func); duke@435: duke@435: // register our extension event duke@435: duke@435: static jvmtiParamInfo event_params[] = { duke@435: { (char*)"JNI Environment", JVMTI_KIND_IN, JVMTI_TYPE_JNIENV, JNI_FALSE }, duke@435: { (char*)"Thread", JVMTI_KIND_IN, JVMTI_TYPE_JTHREAD, JNI_FALSE }, duke@435: { (char*)"Class", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, JNI_FALSE } duke@435: }; duke@435: static jvmtiExtensionEventInfo ext_event = { duke@435: EXT_EVENT_CLASS_UNLOAD, duke@435: (char*)"com.sun.hotspot.events.ClassUnload", duke@435: (char*)"CLASS_UNLOAD event", duke@435: sizeof(event_params)/sizeof(event_params[0]), duke@435: event_params duke@435: }; duke@435: _ext_events->append(&ext_event); duke@435: } duke@435: duke@435: duke@435: // return the list of extension functions duke@435: duke@435: jvmtiError JvmtiExtensions::get_functions(JvmtiEnv* env, duke@435: jint* extension_count_ptr, duke@435: jvmtiExtensionFunctionInfo** extensions) duke@435: { duke@435: guarantee(_ext_functions != NULL, "registration not done"); duke@435: duke@435: ResourceTracker rt(env); duke@435: duke@435: jvmtiExtensionFunctionInfo* ext_funcs; duke@435: jvmtiError err = rt.allocate(_ext_functions->length() * duke@435: sizeof(jvmtiExtensionFunctionInfo), duke@435: (unsigned char**)&ext_funcs); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: duke@435: for (int i=0; i<_ext_functions->length(); i++ ) { duke@435: ext_funcs[i].func = _ext_functions->at(i)->func; duke@435: duke@435: char *id = _ext_functions->at(i)->id; duke@435: err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_funcs[i].id)); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: strcpy(ext_funcs[i].id, id); duke@435: duke@435: char *desc = _ext_functions->at(i)->short_description; duke@435: err = rt.allocate(strlen(desc)+1, duke@435: (unsigned char**)&(ext_funcs[i].short_description)); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: strcpy(ext_funcs[i].short_description, desc); duke@435: duke@435: // params duke@435: duke@435: jint param_count = _ext_functions->at(i)->param_count; duke@435: duke@435: ext_funcs[i].param_count = param_count; duke@435: if (param_count == 0) { duke@435: ext_funcs[i].params = NULL; duke@435: } else { duke@435: err = rt.allocate(param_count*sizeof(jvmtiParamInfo), duke@435: (unsigned char**)&(ext_funcs[i].params)); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: jvmtiParamInfo* src_params = _ext_functions->at(i)->params; duke@435: jvmtiParamInfo* dst_params = ext_funcs[i].params; duke@435: duke@435: for (int j=0; jat(i)->error_count; duke@435: ext_funcs[i].error_count = error_count; duke@435: if (error_count == 0) { duke@435: ext_funcs[i].errors = NULL; duke@435: } else { duke@435: err = rt.allocate(error_count*sizeof(jvmtiError), duke@435: (unsigned char**)&(ext_funcs[i].errors)); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: memcpy(ext_funcs[i].errors, _ext_functions->at(i)->errors, duke@435: error_count*sizeof(jvmtiError)); duke@435: } duke@435: } duke@435: duke@435: *extension_count_ptr = _ext_functions->length(); duke@435: *extensions = ext_funcs; duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: duke@435: duke@435: // return the list of extension events duke@435: duke@435: jvmtiError JvmtiExtensions::get_events(JvmtiEnv* env, duke@435: jint* extension_count_ptr, duke@435: jvmtiExtensionEventInfo** extensions) duke@435: { duke@435: guarantee(_ext_events != NULL, "registration not done"); duke@435: duke@435: ResourceTracker rt(env); duke@435: duke@435: jvmtiExtensionEventInfo* ext_events; duke@435: jvmtiError err = rt.allocate(_ext_events->length() * sizeof(jvmtiExtensionEventInfo), duke@435: (unsigned char**)&ext_events); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: duke@435: for (int i=0; i<_ext_events->length(); i++ ) { duke@435: ext_events[i].extension_event_index = _ext_events->at(i)->extension_event_index; duke@435: duke@435: char *id = _ext_events->at(i)->id; duke@435: err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_events[i].id)); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: strcpy(ext_events[i].id, id); duke@435: duke@435: char *desc = _ext_events->at(i)->short_description; duke@435: err = rt.allocate(strlen(desc)+1, duke@435: (unsigned char**)&(ext_events[i].short_description)); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: strcpy(ext_events[i].short_description, desc); duke@435: duke@435: // params duke@435: duke@435: jint param_count = _ext_events->at(i)->param_count; duke@435: duke@435: ext_events[i].param_count = param_count; duke@435: if (param_count == 0) { duke@435: ext_events[i].params = NULL; duke@435: } else { duke@435: err = rt.allocate(param_count*sizeof(jvmtiParamInfo), duke@435: (unsigned char**)&(ext_events[i].params)); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: jvmtiParamInfo* src_params = _ext_events->at(i)->params; duke@435: jvmtiParamInfo* dst_params = ext_events[i].params; duke@435: duke@435: for (int j=0; jlength(); duke@435: *extensions = ext_events; duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: duke@435: // set callback for an extension event and enable/disable it. duke@435: duke@435: jvmtiError JvmtiExtensions::set_event_callback(JvmtiEnv* env, duke@435: jint extension_event_index, duke@435: jvmtiExtensionEvent callback) duke@435: { duke@435: guarantee(_ext_events != NULL, "registration not done"); duke@435: duke@435: jvmtiExtensionEventInfo* event = NULL; duke@435: duke@435: // if there are extension events registered then validate that the duke@435: // extension_event_index matches one of the registered events. duke@435: if (_ext_events != NULL) { duke@435: for (int i=0; i<_ext_events->length(); i++ ) { duke@435: if (_ext_events->at(i)->extension_event_index == extension_event_index) { duke@435: event = _ext_events->at(i); duke@435: break; duke@435: } duke@435: } duke@435: } duke@435: duke@435: // invalid event index duke@435: if (event == NULL) { duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: } duke@435: duke@435: JvmtiEventController::set_extension_event_callback(env, extension_event_index, duke@435: callback); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: }