JNIUtility

来源:互联网 发布:软件模块化设计方法 编辑:程序博客网 时间:2024/06/05 07:05

#ifndef JNIUtility_H#define JNIUtility_H//////////////////////////////////////////////////////////////////////////#ifdef __cplusplusextern "C" {#endif//////////////////////////////////////////////////////////////////////////#include <jni.h>///////////////////////////////////////////////////////////////////////////* Throw common exceptions *//* Note: these have been macroized in jni_cvm_util.h */void JNU_ThrowNullPointerException(JNIEnv *env, const char *msg);void JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg);void JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg);void JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg);void JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg);void JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg);void JNU_ThrowInternalError(JNIEnv *env, const char *msg);void JNU_ThrowIOException(JNIEnv *env, const char *msg);void JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg);void JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg);void JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg);void JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg);void JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg);void JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg);void JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg);void JNU_ThrowInstantiationException(JNIEnv *env, const char *msg);/* Class constants */jclass JNU_ClassString(JNIEnv *env);jclass JNU_ClassClass(JNIEnv *env);jclass JNU_ClassObject(JNIEnv *env);jclass JNU_ClassThrowable(JNIEnv *env);/* Copy count number of arguments from src to dst. Array bounds and ArrayStoreException are checked. */jint JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, jint count);/* Invoke a object-returning static method, based on class name, * method name, and signature string. * * The caller should check for exceptions by setting hasException * argument. If the caller is not interested in whether an exception * has occurred, pass in NULL. */jvalue JNU_CallStaticMethod(JNIEnv *env, jboolean *hasException, const char *class_name, const char *name, const char *signature, ...);/* Invoke an instance method by name. */jvalue JNU_CallMethod(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *signature, ...);jvalue JNU_CallMethodV(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *signature, va_list args);/* Construct a new object of class, specifiying the class by name, * and specififying which constructor to run and what arguments to * pass to it. * * The method will return an initialized instance if successful. * It will return NULL if an error has occured (for example if * it ran out of memory) and the appropriate Java exception will * have been thrown. */jobject JNU_NewObject(JNIEnv *env, const char *class_name, const char *constructor_sig, ...);/* returns: * 0: object is not an instance of the class named by classname. * 1: object is an instance of the class named by classname. * -1: the class named by classname cannot be found. An exception * has been thrown. */jint JNU_IsInstanceOf(JNIEnv *env, jobject object, char *classname);/* Get or set class and instance fields. * Note that set functions take a variable number of arguments, * but only one argument of the appropriate type can be passed. * For example, to set an integer field i to 100: * * JNU_SetFieldByName(env, &exc, obj, "i", "I", 100); * * To set a float field f to 12.3: * * JNU_SetFieldByName(env, &exc, obj, "f", "F", 12.3); * * The caller should check for exceptions by setting hasException * argument. If the caller is not interested in whether an exception * has occurred, pass in NULL. */jvalue JNU_GetField(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *sig);void JNU_SetField(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *sig, ...);jvalue JNU_GetStaticField(JNIEnv *env, jboolean *hasException, const char *classname, const char *name, const char *sig);void JNU_SetStaticField(JNIEnv *env, jboolean *hasException, const char *classname, const char *name, const char *sig, ...);/* * Calls the .equals method. */jboolean JNU_Equals(JNIEnv *env, jobject object1, jobject object2);/************************************************************************ * Thread calls * * Convenience thread-related calls on the java.lang.Object class. */void JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout);void JNU_Notify(JNIEnv *env, jobject object);void JNU_NotifyAll(JNIEnv *env, jobject object);/************************************************************************ * Miscellaneous utilities used by the class libraries */#define IS_NULL(obj)((obj) == NULL)/************************************************************************ * Debugging utilities */jstring JNU_ToString(JNIEnv *env, jobject object);/*  * Package shorthand for use by native libraries */#define JNU_JAVAPKG"java/lang/"#define JNU_JAVAIOPKG"java/io/"#define JNU_JAVANETPKG"java/net/"/* * Check if the current thread is attached to the VM, and returns * the JNIEnv of the specified version if the thread is attached. * * If the current thread is not attached, this function returns 0. * * If the current thread is attached, this function returns the * JNI environment, or returns (void *)JNI_ERR if the specified * version is not suppored.  */void *JNU_GetEnv(JavaVM *vm, jint version);/* * Warning free access to pointers stored in Java long fields. */#define JNU_GetLongFieldAsPtr(env,obj,id)((void *)(unsigned long)(*(env))->GetLongField((env),(obj),(id)))#define JNU_SetLongFieldFromPtr(env,obj,id,val)(*(env))->SetLongField((env),(obj),(id),(jlong)(unsigned long)(val))//////////////////////////////////////////////////////////////////////////#ifdef __cplusplus}#endif//////////////////////////////////////////////////////////////////////////#endif

#include "JNIUtility.h"#include "NativeHelper/JNIHelp.h"#include <stdio.h>#include <string.h>//////////////////////////////////////////////////////////////////////////void JNU_ThrowNullPointerException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/NullPointerException", msg); }void JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", msg); }void JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/OutOfMemoryError", msg); }void JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/IllegalArgumentException", msg); }void JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/IllegalAccessError", msg); }void JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/IllegalAccessException", msg); }void JNU_ThrowInternalError(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/InternalError", msg); }void JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/NoSuchFieldException", msg); }void JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/NoSuchMethodException", msg); }void JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/ClassNotFoundException", msg); }void JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/NumberFormatException", msg); }void JNU_ThrowIOException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/io/IOException", msg); }void JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/NoSuchFieldError", msg); }void JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/NoSuchMethodError", msg); }void JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/StringIndexOutOfBoundsException", msg); }void JNU_ThrowInstantiationException(JNIEnv *env, const char *msg){ jniThrowException(env, "java/lang/InstantiationException", msg); }//////////////////////////////////////////////////////////////////////////jvalue JNU_CallStaticMethod(JNIEnv *env, jboolean *hasException, const char *class_name, const char *name, const char *signature, ...){jclass clazz;jmethodID mid;va_list args;jvalue result;const char *p= signature;/* find out the return type */while (*p && *p != ')') {p++;}p++;result.i = 0;if (env->EnsureLocalCapacity(3) < 0) {goto done2;}clazz = env->FindClass(class_name);if (clazz == 0) {goto done2;}mid = env->GetStaticMethodID(clazz, name, signature);if (mid == 0) {goto done1;}va_start(args, signature);switch (*p) {case 'V':env->CallStaticVoidMethodV(clazz, mid, args); break;case '[':case 'L':result.l = env->CallStaticObjectMethodV(clazz, mid, args); break;case 'Z':result.z = env->CallStaticBooleanMethodV(clazz, mid, args); break;case 'B':result.b = env->CallStaticByteMethodV(clazz, mid, args); break;case 'C':result.c = env->CallStaticCharMethodV(clazz, mid, args); break;case 'S':result.s = env->CallStaticShortMethodV(clazz, mid, args); break;case 'I':result.i = env->CallStaticIntMethodV(clazz, mid, args); break;case 'J':result.j = env->CallStaticLongMethodV(clazz, mid, args); break;case 'F':result.f = env->CallStaticFloatMethodV(clazz, mid, args); break;case 'D':result.d = env->CallStaticDoubleMethodV(clazz, mid, args); break;default:env->FatalError("JNU_CallStaticMethodByName: illegal signature");break;}va_end(args);done1:env->DeleteLocalRef(clazz);done2:if (hasException) {*hasException = env->ExceptionCheck();}return result;}jvalue JNU_CallMethod(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *signature, ...){jvalue result;va_list args;va_start(args, signature);result = JNU_CallMethodV(env, hasException, obj, name, signature, args); va_end(args);return result;}jvalue JNU_CallMethodV(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *signature, va_list args){jclass clazz;jmethodID mid;jvalue result;const char *p= signature;/* find out the return type */while (*p && *p != ')') {p++;}p++;result.i = 0;if (env->EnsureLocalCapacity(3) < 0) {goto done2;}clazz = env->GetObjectClass(obj);mid = env->GetMethodID(clazz, name, signature);if (mid == 0) {goto done1;}switch (*p) {case 'V':env->CallVoidMethodV(obj, mid, args);break;case '[':case 'L':result.l = env->CallObjectMethodV(obj, mid, args);break;case 'Z':result.z = env->CallBooleanMethodV(obj, mid, args);break;case 'B':result.b = env->CallByteMethodV(obj, mid, args);break;case 'C':result.c = env->CallCharMethodV(obj, mid, args);break;case 'S':result.s = env->CallShortMethodV(obj, mid, args);break;case 'I':result.i = env->CallIntMethodV(obj, mid, args);break;case 'J':result.j = env->CallLongMethodV(obj, mid, args);break;case 'F':result.f = env->CallFloatMethodV(obj, mid, args);break;case 'D':result.d = env->CallDoubleMethodV(obj, mid, args);break;default:env->FatalError("JNU_CallMethodByNameV: illegal signature");break;}done1:env->DeleteLocalRef(clazz);done2:if (hasException) {*hasException = env->ExceptionCheck();}return result;}jobject JNU_NewObject(JNIEnv *env, const char *class_name, const char *constructor_sig, ...){jobject obj= NULL;jclass cls= 0;jmethodID cls_initMID;va_list args;if (env->EnsureLocalCapacity(2) < 0) {goto done;}cls = env->FindClass(class_name);if (cls == 0) {goto done;}cls_initMID = env->GetMethodID(cls, "<init>", constructor_sig);if (cls_initMID == NULL) {goto done;}va_start(args, constructor_sig);obj = env->NewObjectV(cls, cls_initMID, args);va_end(args);done:env->DeleteLocalRef(cls);return obj;}/* Note: JNU_ClassString, JNU_ClassClass, JNU_ClassObject, JNU_ClassThrowable */jclass JNU_ClassString(JNIEnv *env){static jclass cls= 0;if (cls == 0) {jclass c;if (env->EnsureLocalCapacity(1) < 0) {return 0;}c = env->FindClass("java/lang/String");cls = reinterpret_cast<jclass>(env->NewGlobalRef(c));env->DeleteLocalRef(c);}return cls;}jclass JNU_ClassClass(JNIEnv *env){static jclass cls= 0;if (cls == 0) {jclass c;if (env->EnsureLocalCapacity(1) < 0) {return 0;}c = env->FindClass("java/lang/Class");cls = reinterpret_cast<jclass>(env->NewGlobalRef(c));env->DeleteLocalRef(c);}return cls;}jclass JNU_ClassObject(JNIEnv *env){static jclass cls= 0;if (cls == 0) {jclass c;if (env->EnsureLocalCapacity(1) < 0) {return 0;}c = env->FindClass("java/lang/Object");cls = reinterpret_cast<jclass>(env->NewGlobalRef(c));env->DeleteLocalRef(c);}return cls;}jclass JNU_ClassThrowable(JNIEnv *env){static jclass cls= 0;if (cls == 0) {jclass c;if (env->EnsureLocalCapacity(1) < 0) {return 0;}c = env->FindClass("java/lang/Throwable");cls = reinterpret_cast<jclass>(env->NewGlobalRef(c));env->DeleteLocalRef(c);}return cls;}jint JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, jint count){if (env->EnsureLocalCapacity(1) < 0) {return -1;}for (int i = 0; i < count; i++) {jstring p= (jstring) env->GetObjectArrayElement(src, i);env->SetObjectArrayElement(dst, i, p);env->DeleteLocalRef(p);}return 0;}void * JNU_GetEnv(JavaVM *vm, jint version){void *env = NULL;vm->GetEnv(&env, version);return env;}jint JNU_IsInstanceOf(JNIEnv *env, jobject object, char *classname){jclass cls;if (env->EnsureLocalCapacity(1) < 0) {return JNI_ERR;}cls = env->FindClass(classname);if (cls != NULL) {jint result= env->IsInstanceOf(object, cls);env->DeleteLocalRef(cls);return result;}return JNI_ERR;}/************************************************************************ * Debugging utilities */jstring JNU_ToString(JNIEnv *env, jobject object){if (object == NULL) {return env->NewStringUTF("NULL");}else {return reinterpret_cast<jstring>(JNU_CallMethod(env, NULL, object, "toString", "()Ljava/lang/String;").l);}}jvalue JNU_GetField(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *signature){jclass cls;jfieldID fid;jvalue result;result.i = 0;if (env->EnsureLocalCapacity(3) < 0) {goto done2;}cls = env->GetObjectClass(obj);fid = env->GetFieldID(cls, name, signature);if (fid == 0) {goto done1;}switch (*signature) {case '[':case 'L':result.l = env->GetObjectField(obj, fid);break;  case 'Z':result.z = env->GetBooleanField(obj, fid);break;case 'B':result.b = env->GetByteField(obj, fid);break;case 'C':result.c = env->GetCharField(obj, fid);break;case 'S':result.s = env->GetShortField(obj, fid);break;case 'I':result.i = env->GetIntField(obj, fid);break;case 'J':result.j = env->GetLongField(obj, fid);break;case 'F':result.f = env->GetFloatField(obj, fid);break;case 'D':result.d = env->GetDoubleField(obj, fid);break;default:env->FatalError("JNU_GetFieldByName: illegal signature");break;}done1:env->DeleteLocalRef(cls);done2:if (hasException) {*hasException = env->ExceptionCheck();}return result;}void JNU_SetField(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *signature, ...){jclass cls;jfieldID fid;va_list args;if (env->EnsureLocalCapacity(3) < 0) {goto done2;}cls = env->GetObjectClass(obj);fid = env->GetFieldID(cls, name, signature);if (fid == 0) {goto done1;}/* When passing arguments via '...', each argument is converted to int   or double (as appropriate). When we pick off the mystery argument   with va_arg(), we need to use the type of argument as passed, not   the type we want. The compiler will convert the argument back to the   proper type when passing it to Set<type>Field(). */va_start(args, signature);switch (*signature) {case '[':case 'L':env->SetObjectField(obj, fid, va_arg(args, jobject));break;  case 'Z':env->SetBooleanField(obj, fid, (jboolean) va_arg(args, jint));break;case 'B':env->SetByteField(obj, fid, (jbyte) va_arg(args, jint));break;case 'C':env->SetCharField(obj, fid, (jchar) va_arg(args, jint));break;case 'S':env->SetShortField(obj, fid, (jshort) va_arg(args, jint));break;case 'I':env->SetIntField(obj, fid, va_arg(args, jint));break;case 'J':env->SetLongField(obj, fid, va_arg(args, jlong));break;case 'F':env->SetFloatField(obj, fid, (jfloat) va_arg(args, jdouble));break;case 'D':env->SetDoubleField(obj, fid, va_arg(args, jdouble));break;default:env->FatalError("JNU_SetFieldByName: illegal signature");break;}va_end(args);done1:env->DeleteLocalRef(cls);done2:if (hasException) {*hasException = env->ExceptionCheck();}}jvalue JNU_GetStaticField(JNIEnv *env, jboolean *hasException, const char *classname, const char *name, const char *signature){jclass cls;jfieldID fid;jvalue result;result.i = 0;if (env->EnsureLocalCapacity(3) < 0) {goto done2;}cls = env->FindClass(classname);if (cls == 0) {goto done2;}fid = env->GetStaticFieldID(cls, name, signature);if (fid == 0) {goto done1;}switch (*signature) {case '[':case 'L':result.l = env->GetStaticObjectField(cls, fid);break;case 'Z':result.z = env->GetStaticBooleanField(cls, fid);break;case 'B':result.b = env->GetStaticByteField(cls, fid);break;case 'C':result.c = env->GetStaticCharField(cls, fid);break;case 'S':result.s = env->GetStaticShortField(cls, fid);break;case 'I':result.i = env->GetStaticIntField(cls, fid);break;case 'J':result.j = env->GetStaticLongField(cls, fid);break;case 'F':result.f = env->GetStaticFloatField(cls, fid);break;case 'D':result.d = env->GetStaticDoubleField(cls, fid);break;default:env->FatalError("JNU_GetStaticFieldByName: illegal signature");break;}done1:env->DeleteLocalRef(cls);done2:if (hasException) {*hasException = env->ExceptionCheck();}return result;}void JNU_SetStaticField(JNIEnv *env, jboolean *hasException, const char *classname, const char *name, const char *signature, ...){jclass cls;jfieldID fid;va_list args;if (env->EnsureLocalCapacity(3) < 0) {goto done2;}cls = env->FindClass(classname);if (cls == 0) {goto done2;}fid = env->GetStaticFieldID(cls, name, signature);if (fid == 0) {goto done1;}/* When passing arguments via '...', each argument is converted to int   or double (as appropriate). When we pick off the mystery argument   with va_arg(), we need to use the type of argument as passed, not   the type we want. The compiler will convert the argument back to the   proper type when passing it to SetStatic<type>Field(). */va_start(args, signature);switch (*signature) {case '[':case 'L':env->SetStaticObjectField(cls, fid, va_arg(args, jobject));break;  case 'Z':env->SetStaticBooleanField(cls, fid, (jboolean) va_arg(args, jint));break;case 'B':env->SetStaticByteField(cls, fid, (jbyte) va_arg(args, jint));break;case 'C':env->SetStaticCharField(cls, fid, (jchar) va_arg(args, jint));break;case 'S':env->SetStaticShortField(cls, fid, (jshort) va_arg(args, jint));break;case 'I':env->SetStaticIntField(cls, fid, va_arg(args, jint));break;case 'J':env->SetStaticLongField(cls, fid, va_arg(args, jlong));break;case 'F':env->SetStaticFloatField(cls, fid, (jfloat) va_arg(args, jdouble));break;case 'D':env->SetStaticDoubleField(cls, fid, va_arg(args, jdouble));break;default:env->FatalError("JNU_SetStaticFieldByName: illegal signature");break;}va_end(args);done1:env->DeleteLocalRef(cls);done2:if (hasException) {*hasException = env->ExceptionCheck();}}jboolean JNU_Equals(JNIEnv *env, jobject object1, jobject object2){return JNU_CallMethod(env, NULL, object1, "equals", "(Ljava/lang/Object;)Z", object2).z;}void JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout){if (object == NULL) {JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument");return;}JNU_CallMethod(env, NULL, object, "wait", "(J)V", timeout);}void JNU_Notify(JNIEnv *env, jobject object){if (object == NULL) {JNU_ThrowNullPointerException(env, "JNU_Notify argument");return;}JNU_CallMethod(env, NULL, object, "notify", "()V");}void JNU_NotifyAll(JNIEnv *env, jobject object){if (object == NULL) {JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument");return;}JNU_CallMethod(env, NULL, object, "notifyAll", "()V");}



0 0