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
32JNIEXPORT 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
45JNIEXPORT 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
127static 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
136static 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
145static 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
154static 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
163static 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
172static 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
181static 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
190static 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
199JNIEXPORT 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