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, 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 | |
90 | jvmtiError 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 | |
179 | jvmtiError 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 | |
250 | jvmtiError 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 | |