1 | /* |
2 | * Copyright (c) 2003, 2015, 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. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle in the LICENSE file that accompanied this code. |
10 | * |
11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | * version 2 for more details (a copy is included in the LICENSE file that |
15 | * accompanied this code). |
16 | * |
17 | * You should have received a copy of the GNU General Public License version |
18 | * 2 along with this work; if not, write to the Free Software Foundation, |
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
20 | * |
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * questions. |
24 | */ |
25 | |
26 | #include <stdlib.h> |
27 | #include <stdio.h> |
28 | #include <jni.h> |
29 | #include "management_ext.h" |
30 | #include "com_sun_management_internal_GcInfoBuilder.h" |
31 | |
32 | JNIEXPORT jint JNICALL Java_com_sun_management_internal_GcInfoBuilder_getNumGcExtAttributes |
33 | (JNIEnv *env, jobject dummy, jobject gc) { |
34 | jlong value; |
35 | |
36 | if (gc == NULL) { |
37 | JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean" ); |
38 | return 0; |
39 | } |
40 | value = jmm_interface->GetLongAttribute(env, gc, |
41 | JMM_GC_EXT_ATTRIBUTE_INFO_SIZE); |
42 | return (jint) value; |
43 | } |
44 | |
45 | JNIEXPORT void JNICALL Java_com_sun_management_internal_GcInfoBuilder_fillGcAttributeInfo |
46 | (JNIEnv *env, jobject dummy, jobject gc, |
47 | jint num_attributes, jobjectArray attributeNames, |
48 | jcharArray types, jobjectArray descriptions) { |
49 | |
50 | jmmExtAttributeInfo* ext_att_info; |
51 | jchar* nativeTypes; |
52 | jstring attName = NULL; |
53 | jstring desc = NULL; |
54 | jint ret = 0; |
55 | jint i; |
56 | |
57 | if (gc == NULL) { |
58 | JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean" ); |
59 | return; |
60 | } |
61 | |
62 | if (num_attributes <= 0) { |
63 | JNU_ThrowIllegalArgumentException(env, "Invalid num_attributes" ); |
64 | return; |
65 | } |
66 | |
67 | ext_att_info = (jmmExtAttributeInfo*) malloc((size_t)num_attributes * |
68 | sizeof(jmmExtAttributeInfo)); |
69 | if (ext_att_info == NULL) { |
70 | JNU_ThrowOutOfMemoryError(env, 0); |
71 | return; |
72 | } |
73 | ret = jmm_interface->GetGCExtAttributeInfo(env, gc, |
74 | ext_att_info, num_attributes); |
75 | if (ret != num_attributes) { |
76 | JNU_ThrowInternalError(env, "Unexpected num_attributes" ); |
77 | free(ext_att_info); |
78 | return; |
79 | } |
80 | |
81 | nativeTypes = (jchar*) malloc((size_t)num_attributes * sizeof(jchar)); |
82 | if (nativeTypes == NULL) { |
83 | free(ext_att_info); |
84 | JNU_ThrowOutOfMemoryError(env, 0); |
85 | return; |
86 | } |
87 | for (i = 0; i < num_attributes; i++) { |
88 | nativeTypes[i] = ext_att_info[i].type; |
89 | attName = (*env)->NewStringUTF(env, ext_att_info[i].name); |
90 | if ((*env)->ExceptionCheck(env)) { |
91 | free(ext_att_info); |
92 | free(nativeTypes); |
93 | return; |
94 | } |
95 | |
96 | (*env)->SetObjectArrayElement(env, attributeNames, i, attName); |
97 | if ((*env)->ExceptionCheck(env)) { |
98 | free(ext_att_info); |
99 | free(nativeTypes); |
100 | return; |
101 | } |
102 | |
103 | desc = (*env)->NewStringUTF(env, ext_att_info[i].description); |
104 | if ((*env)->ExceptionCheck(env)) { |
105 | free(ext_att_info); |
106 | free(nativeTypes); |
107 | return; |
108 | } |
109 | |
110 | (*env)->SetObjectArrayElement(env, descriptions, i, desc); |
111 | if ((*env)->ExceptionCheck(env)) { |
112 | free(ext_att_info); |
113 | free(nativeTypes); |
114 | return; |
115 | } |
116 | } |
117 | (*env)->SetCharArrayRegion(env, types, 0, num_attributes, nativeTypes); |
118 | |
119 | if (ext_att_info != NULL) { |
120 | free(ext_att_info); |
121 | } |
122 | if (nativeTypes != NULL) { |
123 | free(nativeTypes); |
124 | } |
125 | } |
126 | |
127 | static void setLongValueAtObjectArray(JNIEnv *env, jobjectArray array, |
128 | jsize index, jlong value) { |
129 | static const char* class_name = "java/lang/Long" ; |
130 | static const char* signature = "(J)V" ; |
131 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
132 | |
133 | (*env)->SetObjectArrayElement(env, array, index, obj); |
134 | } |
135 | |
136 | static void setBooleanValueAtObjectArray(JNIEnv *env, jobjectArray array, |
137 | jsize index, jboolean value) { |
138 | static const char* class_name = "java/lang/Boolean" ; |
139 | static const char* signature = "(Z)V" ; |
140 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
141 | |
142 | (*env)->SetObjectArrayElement(env, array, index, obj); |
143 | } |
144 | |
145 | static void setByteValueAtObjectArray(JNIEnv *env, jobjectArray array, |
146 | jsize index, jbyte value) { |
147 | static const char* class_name = "java/lang/Byte" ; |
148 | static const char* signature = "(B)V" ; |
149 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
150 | |
151 | (*env)->SetObjectArrayElement(env, array, index, obj); |
152 | } |
153 | |
154 | static void setIntValueAtObjectArray(JNIEnv *env, jobjectArray array, |
155 | jsize index, jint value) { |
156 | static const char* class_name = "java/lang/Integer" ; |
157 | static const char* signature = "(I)V" ; |
158 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
159 | |
160 | (*env)->SetObjectArrayElement(env, array, index, obj); |
161 | } |
162 | |
163 | static void setShortValueAtObjectArray(JNIEnv *env, jobjectArray array, |
164 | jsize index, jshort value) { |
165 | static const char* class_name = "java/lang/Short" ; |
166 | static const char* signature = "(S)V" ; |
167 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
168 | |
169 | (*env)->SetObjectArrayElement(env, array, index, obj); |
170 | } |
171 | |
172 | static void setDoubleValueAtObjectArray(JNIEnv *env, jobjectArray array, |
173 | jsize index, jdouble value) { |
174 | static const char* class_name = "java/lang/Double" ; |
175 | static const char* signature = "(D)V" ; |
176 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
177 | |
178 | (*env)->SetObjectArrayElement(env, array, index, obj); |
179 | } |
180 | |
181 | static void setFloatValueAtObjectArray(JNIEnv *env, jobjectArray array, |
182 | jsize index, jfloat value) { |
183 | static const char* class_name = "java/lang/Float" ; |
184 | static const char* signature = "(D)V" ; |
185 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
186 | |
187 | (*env)->SetObjectArrayElement(env, array, index, obj); |
188 | } |
189 | |
190 | static void setCharValueAtObjectArray(JNIEnv *env, jobjectArray array, |
191 | jsize index, jchar value) { |
192 | static const char* class_name = "java/lang/Character" ; |
193 | static const char* signature = "(C)V" ; |
194 | jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
195 | |
196 | (*env)->SetObjectArrayElement(env, array, index, obj); |
197 | } |
198 | |
199 | JNIEXPORT jobject JNICALL Java_com_sun_management_internal_GcInfoBuilder_getLastGcInfo0 |
200 | (JNIEnv *env, jobject builder, jobject gc, |
201 | jint ext_att_count, jobjectArray ext_att_values, jcharArray ext_att_types, |
202 | jobjectArray usageBeforeGC, jobjectArray usageAfterGC) { |
203 | |
204 | jmmGCStat gc_stat; |
205 | jchar* nativeTypes; |
206 | jsize i; |
207 | jvalue v; |
208 | |
209 | if (gc == NULL) { |
210 | JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean" ); |
211 | return 0; |
212 | } |
213 | |
214 | if (ext_att_count <= 0) { |
215 | JNU_ThrowIllegalArgumentException(env, "Invalid ext_att_count" ); |
216 | return 0; |
217 | } |
218 | |
219 | gc_stat.usage_before_gc = usageBeforeGC; |
220 | gc_stat.usage_after_gc = usageAfterGC; |
221 | gc_stat.gc_ext_attribute_values_size = ext_att_count; |
222 | if (ext_att_count > 0) { |
223 | gc_stat.gc_ext_attribute_values = (jvalue*) malloc((size_t)ext_att_count * |
224 | sizeof(jvalue)); |
225 | if (gc_stat.gc_ext_attribute_values == NULL) { |
226 | JNU_ThrowOutOfMemoryError(env, 0); |
227 | return 0; |
228 | } |
229 | } else { |
230 | gc_stat.gc_ext_attribute_values = NULL; |
231 | } |
232 | |
233 | |
234 | jmm_interface->GetLastGCStat(env, gc, &gc_stat); |
235 | if (gc_stat.gc_index == 0) { |
236 | if (gc_stat.gc_ext_attribute_values != NULL) { |
237 | free(gc_stat.gc_ext_attribute_values); |
238 | } |
239 | return 0; |
240 | } |
241 | |
242 | // convert the ext_att_types to native types |
243 | nativeTypes = (jchar*) malloc((size_t)ext_att_count * sizeof(jchar)); |
244 | if (nativeTypes == NULL) { |
245 | if (gc_stat.gc_ext_attribute_values != NULL) { |
246 | free(gc_stat.gc_ext_attribute_values); |
247 | } |
248 | JNU_ThrowOutOfMemoryError(env, 0); |
249 | return 0; |
250 | } |
251 | (*env)->GetCharArrayRegion(env, ext_att_types, 0, ext_att_count, nativeTypes); |
252 | for (i = 0; i < ext_att_count; i++) { |
253 | v = gc_stat.gc_ext_attribute_values[i]; |
254 | switch (nativeTypes[i]) { |
255 | case 'Z': |
256 | setBooleanValueAtObjectArray(env, ext_att_values, i, v.z); |
257 | break; |
258 | case 'B': |
259 | setByteValueAtObjectArray(env, ext_att_values, i, v.b); |
260 | break; |
261 | case 'C': |
262 | setCharValueAtObjectArray(env, ext_att_values, i, v.c); |
263 | break; |
264 | case 'S': |
265 | setShortValueAtObjectArray(env, ext_att_values, i, v.s); |
266 | break; |
267 | case 'I': |
268 | setIntValueAtObjectArray(env, ext_att_values, i, v.i); |
269 | break; |
270 | case 'J': |
271 | setLongValueAtObjectArray(env, ext_att_values, i, v.j); |
272 | break; |
273 | case 'F': |
274 | setFloatValueAtObjectArray(env, ext_att_values, i, v.f); |
275 | break; |
276 | case 'D': |
277 | setDoubleValueAtObjectArray(env, ext_att_values, i, v.d); |
278 | break; |
279 | default: |
280 | if (gc_stat.gc_ext_attribute_values != NULL) { |
281 | free(gc_stat.gc_ext_attribute_values); |
282 | } |
283 | if (nativeTypes != NULL) { |
284 | free(nativeTypes); |
285 | } |
286 | JNU_ThrowInternalError(env, "Unsupported attribute type" ); |
287 | return 0; |
288 | } |
289 | } |
290 | if (gc_stat.gc_ext_attribute_values != NULL) { |
291 | free(gc_stat.gc_ext_attribute_values); |
292 | } |
293 | if (nativeTypes != NULL) { |
294 | free(nativeTypes); |
295 | } |
296 | |
297 | return JNU_NewObjectByName(env, |
298 | "com/sun/management/GcInfo" , |
299 | "(Lcom/sun/management/internal/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V" , |
300 | builder, |
301 | gc_stat.gc_index, |
302 | gc_stat.start_time, |
303 | gc_stat.end_time, |
304 | usageBeforeGC, |
305 | usageAfterGC, |
306 | ext_att_values); |
307 | } |
308 | |