| /* |
| * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <jni.h> |
| #include "management.h" |
| #include "sun_management_GcInfoBuilder.h" |
| |
| JNIEXPORT jint JNICALL Java_sun_management_GcInfoBuilder_getNumGcExtAttributes |
| (JNIEnv *env, jobject dummy, jobject gc) { |
| jlong value; |
| |
| if (gc == NULL) { |
| JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); |
| return 0; |
| } |
| value = jmm_interface->GetLongAttribute(env, gc, |
| JMM_GC_EXT_ATTRIBUTE_INFO_SIZE); |
| return (jint) value; |
| } |
| |
| JNIEXPORT void JNICALL Java_sun_management_GcInfoBuilder_fillGcAttributeInfo |
| (JNIEnv *env, jobject dummy, jobject gc, |
| jint num_attributes, jobjectArray attributeNames, |
| jcharArray types, jobjectArray descriptions) { |
| |
| jmmExtAttributeInfo* ext_att_info; |
| jchar* nativeTypes; |
| jstring attName = NULL; |
| jstring desc = NULL; |
| jint ret = 0; |
| jint i; |
| |
| if (gc == NULL) { |
| JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); |
| return; |
| } |
| |
| if (num_attributes == 0) { |
| JNU_ThrowIllegalArgumentException(env, "Invalid num_attributes"); |
| return; |
| } |
| |
| ext_att_info = (jmmExtAttributeInfo*) malloc(num_attributes * |
| sizeof(jmmExtAttributeInfo)); |
| if (ext_att_info == NULL) { |
| JNU_ThrowOutOfMemoryError(env, 0); |
| return; |
| } |
| ret = jmm_interface->GetGCExtAttributeInfo(env, gc, |
| ext_att_info, num_attributes); |
| if (ret != num_attributes) { |
| JNU_ThrowInternalError(env, "Unexpected num_attributes"); |
| free(ext_att_info); |
| return; |
| } |
| |
| nativeTypes = (jchar*) malloc(num_attributes * sizeof(jchar)); |
| if (nativeTypes == NULL) { |
| free(ext_att_info); |
| JNU_ThrowOutOfMemoryError(env, 0); |
| return; |
| } |
| for (i = 0; i < num_attributes; i++) { |
| nativeTypes[i] = ext_att_info[i].type; |
| attName = (*env)->NewStringUTF(env, ext_att_info[i].name); |
| desc = (*env)->NewStringUTF(env, ext_att_info[i].description); |
| (*env)->SetObjectArrayElement(env, attributeNames, i, attName); |
| (*env)->SetObjectArrayElement(env, descriptions, i, desc); |
| } |
| (*env)->SetCharArrayRegion(env, types, 0, num_attributes, nativeTypes); |
| |
| if (ext_att_info != NULL) { |
| free(ext_att_info); |
| } |
| if (nativeTypes != NULL) { |
| free(nativeTypes); |
| } |
| } |
| |
| static void setLongValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jlong value) { |
| static const char* class_name = "java/lang/Long"; |
| static const char* signature = "(J)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| static void setBooleanValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jboolean value) { |
| static const char* class_name = "java/lang/Boolean"; |
| static const char* signature = "(Z)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| static void setByteValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jbyte value) { |
| static const char* class_name = "java/lang/Byte"; |
| static const char* signature = "(B)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| static void setIntValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jint value) { |
| static const char* class_name = "java/lang/Integer"; |
| static const char* signature = "(I)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| static void setShortValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jshort value) { |
| static const char* class_name = "java/lang/Short"; |
| static const char* signature = "(S)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| static void setDoubleValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jdouble value) { |
| static const char* class_name = "java/lang/Double"; |
| static const char* signature = "(D)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| static void setFloatValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jfloat value) { |
| static const char* class_name = "java/lang/Float"; |
| static const char* signature = "(D)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| static void setCharValueAtObjectArray(JNIEnv *env, jobjectArray array, |
| jsize index, jchar value) { |
| static const char* class_name = "java/lang/Character"; |
| static const char* signature = "(C)V"; |
| jobject obj = JNU_NewObjectByName(env, class_name, signature, value); |
| |
| (*env)->SetObjectArrayElement(env, array, index, obj); |
| } |
| |
| JNIEXPORT jobject JNICALL Java_sun_management_GcInfoBuilder_getLastGcInfo0 |
| (JNIEnv *env, jobject builder, jobject gc, |
| jint ext_att_count, jobjectArray ext_att_values, jcharArray ext_att_types, |
| jobjectArray usageBeforeGC, jobjectArray usageAfterGC) { |
| |
| jmmGCStat gc_stat; |
| jchar* nativeTypes; |
| jsize i; |
| jvalue v; |
| |
| if (gc == NULL) { |
| JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); |
| return 0; |
| } |
| |
| gc_stat.usage_before_gc = usageBeforeGC; |
| gc_stat.usage_after_gc = usageAfterGC; |
| gc_stat.gc_ext_attribute_values_size = ext_att_count; |
| if (ext_att_count > 0) { |
| gc_stat.gc_ext_attribute_values = (jvalue*) malloc(ext_att_count * |
| sizeof(jvalue)); |
| if (gc_stat.gc_ext_attribute_values == NULL) { |
| JNU_ThrowOutOfMemoryError(env, 0); |
| return 0; |
| } |
| } else { |
| gc_stat.gc_ext_attribute_values = NULL; |
| } |
| |
| |
| jmm_interface->GetLastGCStat(env, gc, &gc_stat); |
| if (gc_stat.gc_index == 0) { |
| if (gc_stat.gc_ext_attribute_values != NULL) { |
| free(gc_stat.gc_ext_attribute_values); |
| } |
| return 0; |
| } |
| |
| // convert the ext_att_types to native types |
| nativeTypes = (jchar*) malloc(ext_att_count * sizeof(jchar)); |
| if (nativeTypes == NULL) { |
| if (gc_stat.gc_ext_attribute_values != NULL) { |
| free(gc_stat.gc_ext_attribute_values); |
| } |
| JNU_ThrowOutOfMemoryError(env, 0); |
| return 0; |
| } |
| (*env)->GetCharArrayRegion(env, ext_att_types, 0, ext_att_count, nativeTypes); |
| for (i = 0; i < ext_att_count; i++) { |
| v = gc_stat.gc_ext_attribute_values[i]; |
| switch (nativeTypes[i]) { |
| case 'Z': |
| setBooleanValueAtObjectArray(env, ext_att_values, i, v.z); |
| break; |
| case 'B': |
| setByteValueAtObjectArray(env, ext_att_values, i, v.b); |
| break; |
| case 'C': |
| setCharValueAtObjectArray(env, ext_att_values, i, v.c); |
| break; |
| case 'S': |
| setShortValueAtObjectArray(env, ext_att_values, i, v.s); |
| break; |
| case 'I': |
| setIntValueAtObjectArray(env, ext_att_values, i, v.i); |
| break; |
| case 'J': |
| setLongValueAtObjectArray(env, ext_att_values, i, v.j); |
| break; |
| case 'F': |
| setFloatValueAtObjectArray(env, ext_att_values, i, v.f); |
| break; |
| case 'D': |
| setDoubleValueAtObjectArray(env, ext_att_values, i, v.d); |
| break; |
| default: |
| if (gc_stat.gc_ext_attribute_values != NULL) { |
| free(gc_stat.gc_ext_attribute_values); |
| } |
| if (nativeTypes != NULL) { |
| free(nativeTypes); |
| } |
| JNU_ThrowInternalError(env, "Unsupported attribute type"); |
| return 0; |
| } |
| } |
| if (gc_stat.gc_ext_attribute_values != NULL) { |
| free(gc_stat.gc_ext_attribute_values); |
| } |
| if (nativeTypes != NULL) { |
| free(nativeTypes); |
| } |
| |
| return JNU_NewObjectByName(env, |
| "com/sun/management/GcInfo", |
| "(Lsun/management/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V", |
| builder, |
| gc_stat.gc_index, |
| gc_stat.start_time, |
| gc_stat.end_time, |
| usageBeforeGC, |
| usageAfterGC, |
| ext_att_values); |
| } |