jvmtiExtensions.cpp revision 0:a61af66fc99e
1/*
2 * Copyright 2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25# include "incls/_precompiled.incl"
26# include "incls/_jvmtiExtensions.cpp.incl"
27
28// the list of extension functions
29GrowableArray<jvmtiExtensionFunctionInfo*>* JvmtiExtensions::_ext_functions;
30
31// the list of extension events
32GrowableArray<jvmtiExtensionEventInfo*>* JvmtiExtensions::_ext_events;
33
34
35// extension function
36static jvmtiError JNICALL IsClassUnloadingEnabled(const jvmtiEnv* env, jboolean* enabled, ...) {
37  if (enabled == NULL) {
38    return JVMTI_ERROR_NULL_POINTER;
39  }
40  *enabled = (jboolean)ClassUnloading;
41  return JVMTI_ERROR_NONE;
42}
43
44// register extension functions and events. In this implementation we
45// have a single extension function (to prove the API) that tests if class
46// unloading is enabled or disabled. We also have a single extension event
47// EXT_EVENT_CLASS_UNLOAD which is used to provide the JVMDI_EVENT_CLASS_UNLOAD
48// event. The function and the event are registered here.
49//
50void JvmtiExtensions::register_extensions() {
51  _ext_functions = new (ResourceObj::C_HEAP) GrowableArray<jvmtiExtensionFunctionInfo*>(1,true);
52  _ext_events = new (ResourceObj::C_HEAP) GrowableArray<jvmtiExtensionEventInfo*>(1,true);
53
54  // register our extension function
55  static jvmtiParamInfo func_params[] = {
56    { (char*)"IsClassUnloadingEnabled", JVMTI_KIND_OUT,  JVMTI_TYPE_JBOOLEAN, JNI_FALSE }
57  };
58  static jvmtiExtensionFunctionInfo ext_func = {
59    (jvmtiExtensionFunction)IsClassUnloadingEnabled,
60    (char*)"com.sun.hotspot.functions.IsClassUnloadingEnabled",
61    (char*)"Tell if class unloading is enabled (-noclassgc)",
62    sizeof(func_params)/sizeof(func_params[0]),
63    func_params,
64    0,              // no non-universal errors
65    NULL
66  };
67  _ext_functions->append(&ext_func);
68
69  // register our extension event
70
71  static jvmtiParamInfo event_params[] = {
72    { (char*)"JNI Environment", JVMTI_KIND_IN, JVMTI_TYPE_JNIENV, JNI_FALSE },
73    { (char*)"Thread", JVMTI_KIND_IN, JVMTI_TYPE_JTHREAD, JNI_FALSE },
74    { (char*)"Class", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, 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
89jvmtiError 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
178jvmtiError 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
249jvmtiError 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}
278