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
30GrowableArray<jvmtiExtensionFunctionInfo*>* JvmtiExtensions::_ext_functions;
31
32// the list of extension events
33GrowableArray<jvmtiExtensionEventInfo*>* JvmtiExtensions::_ext_events;
34
35
36// extension function
37static 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//
51void 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, JVMTI_TYPE_JNIENV, JNI_FALSE },
74 { (char*)"Thread", JVMTI_KIND_IN, JVMTI_TYPE_JTHREAD, JNI_FALSE },
75 { (char*)"Class", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, JNI_FALSE }
76 };
77 static jvmtiExtensionEventInfo ext_event = {
78 EXT_EVENT_CLASS_UNLOAD,
79 (char*)"com.sun.hotspot.events.ClassUnload",
80 (char*)"CLASS_UNLOAD event",
81 sizeof(event_params)/sizeof(event_params[0]),
82 event_params
83 };
84 _ext_events->append(&ext_event);
85}
86
87
88// return the list of extension functions
89
90jvmtiError JvmtiExtensions::get_functions(JvmtiEnv* env,
91 jint* extension_count_ptr,
92 jvmtiExtensionFunctionInfo** extensions)
93{
94 guarantee(_ext_functions != NULL, "registration not done");
95
96 ResourceTracker rt(env);
97
98 jvmtiExtensionFunctionInfo* ext_funcs;
99 jvmtiError err = rt.allocate(_ext_functions->length() *
100 sizeof(jvmtiExtensionFunctionInfo),
101 (unsigned char**)&ext_funcs);
102 if (err != JVMTI_ERROR_NONE) {
103 return err;
104 }
105
106 for (int i=0; i<_ext_functions->length(); i++ ) {
107 ext_funcs[i].func = _ext_functions->at(i)->func;
108
109 char *id = _ext_functions->at(i)->id;
110 err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_funcs[i].id));
111 if (err != JVMTI_ERROR_NONE) {
112 return err;
113 }
114 strcpy(ext_funcs[i].id, id);
115
116 char *desc = _ext_functions->at(i)->short_description;
117 err = rt.allocate(strlen(desc)+1,
118 (unsigned char**)&(ext_funcs[i].short_description));
119 if (err != JVMTI_ERROR_NONE) {
120 return err;
121 }
122 strcpy(ext_funcs[i].short_description, desc);
123
124 // params
125
126 jint param_count = _ext_functions->at(i)->param_count;
127
128 ext_funcs[i].param_count = param_count;
129 if (param_count == 0) {
130 ext_funcs[i].params = NULL;
131 } else {
132 err = rt.allocate(param_count*sizeof(jvmtiParamInfo),
133 (unsigned char**)&(ext_funcs[i].params));
134 if (err != JVMTI_ERROR_NONE) {
135 return err;
136 }
137 jvmtiParamInfo* src_params = _ext_functions->at(i)->params;
138 jvmtiParamInfo* dst_params = ext_funcs[i].params;
139
140 for (int j=0; j<param_count; j++) {
141 err = rt.allocate(strlen(src_params[j].name)+1,
142 (unsigned char**)&(dst_params[j].name));
143 if (err != JVMTI_ERROR_NONE) {
144 return err;
145 }
146 strcpy(dst_params[j].name, src_params[j].name);
147
148 dst_params[j].kind = src_params[j].kind;
149 dst_params[j].base_type = src_params[j].base_type;
150 dst_params[j].null_ok = src_params[j].null_ok;
151 }
152 }
153
154 // errors
155
156 jint error_count = _ext_functions->at(i)->error_count;
157 ext_funcs[i].error_count = error_count;
158 if (error_count == 0) {
159 ext_funcs[i].errors = NULL;
160 } else {
161 err = rt.allocate(error_count*sizeof(jvmtiError),
162 (unsigned char**)&(ext_funcs[i].errors));
163 if (err != JVMTI_ERROR_NONE) {
164 return err;
165 }
166 memcpy(ext_funcs[i].errors, _ext_functions->at(i)->errors,
167 error_count*sizeof(jvmtiError));
168 }
169 }
170
171 *extension_count_ptr = _ext_functions->length();
172 *extensions = ext_funcs;
173 return JVMTI_ERROR_NONE;
174}
175
176
177// return the list of extension events
178
179jvmtiError JvmtiExtensions::get_events(JvmtiEnv* env,
180 jint* extension_count_ptr,
181 jvmtiExtensionEventInfo** extensions)
182{
183 guarantee(_ext_events != NULL, "registration not done");
184
185 ResourceTracker rt(env);
186
187 jvmtiExtensionEventInfo* ext_events;
188 jvmtiError err = rt.allocate(_ext_events->length() * sizeof(jvmtiExtensionEventInfo),
189 (unsigned char**)&ext_events);
190 if (err != JVMTI_ERROR_NONE) {
191 return err;
192 }
193
194 for (int i=0; i<_ext_events->length(); i++ ) {
195 ext_events[i].extension_event_index = _ext_events->at(i)->extension_event_index;
196
197 char *id = _ext_events->at(i)->id;
198 err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_events[i].id));
199 if (err != JVMTI_ERROR_NONE) {
200 return err;
201 }
202 strcpy(ext_events[i].id, id);
203
204 char *desc = _ext_events->at(i)->short_description;
205 err = rt.allocate(strlen(desc)+1,
206 (unsigned char**)&(ext_events[i].short_description));
207 if (err != JVMTI_ERROR_NONE) {
208 return err;
209 }
210 strcpy(ext_events[i].short_description, desc);
211
212 // params
213
214 jint param_count = _ext_events->at(i)->param_count;
215
216 ext_events[i].param_count = param_count;
217 if (param_count == 0) {
218 ext_events[i].params = NULL;
219 } else {
220 err = rt.allocate(param_count*sizeof(jvmtiParamInfo),
221 (unsigned char**)&(ext_events[i].params));
222 if (err != JVMTI_ERROR_NONE) {
223 return err;
224 }
225 jvmtiParamInfo* src_params = _ext_events->at(i)->params;
226 jvmtiParamInfo* dst_params = ext_events[i].params;
227
228 for (int j=0; j<param_count; j++) {
229 err = rt.allocate(strlen(src_params[j].name)+1,
230 (unsigned char**)&(dst_params[j].name));
231 if (err != JVMTI_ERROR_NONE) {
232 return err;
233 }
234 strcpy(dst_params[j].name, src_params[j].name);
235
236 dst_params[j].kind = src_params[j].kind;
237 dst_params[j].base_type = src_params[j].base_type;
238 dst_params[j].null_ok = src_params[j].null_ok;
239 }
240 }
241 }
242
243 *extension_count_ptr = _ext_events->length();
244 *extensions = ext_events;
245 return JVMTI_ERROR_NONE;
246}
247
248// set callback for an extension event and enable/disable it.
249
250jvmtiError JvmtiExtensions::set_event_callback(JvmtiEnv* env,
251 jint extension_event_index,
252 jvmtiExtensionEvent callback)
253{
254 guarantee(_ext_events != NULL, "registration not done");
255
256 jvmtiExtensionEventInfo* event = NULL;
257
258 // if there are extension events registered then validate that the
259 // extension_event_index matches one of the registered events.
260 if (_ext_events != NULL) {
261 for (int i=0; i<_ext_events->length(); i++ ) {
262 if (_ext_events->at(i)->extension_event_index == extension_event_index) {
263 event = _ext_events->at(i);
264 break;
265 }
266 }
267 }
268
269 // invalid event index
270 if (event == NULL) {
271 return JVMTI_ERROR_ILLEGAL_ARGUMENT;
272 }
273
274 JvmtiEventController::set_extension_event_callback(env, extension_event_index,
275 callback);
276
277 return JVMTI_ERROR_NONE;
278}
279