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