Android JNI静态和动态注册 、Java Reflect(C或C++层反射和JAVA层反射)、Java 可变参数(JNI实现)
2018-01-09 09:13
615 查看
#PS:要转载请注明出处,本人版权所有
#PS:这个只是 《 我自己 》理解,如果和你的
#原则相冲突,请谅解,勿喷
由于最近重新接触了部分Android相关的东西,对一些需要混合编程的手段做了整理,同时也对Java中常见的反射技术进行归纳总结。(本文适合知道JNI和反射是什么鬼的人阅读)(可变参数实现在JNI部分的IoctlGpio方法)
先来看一张来至于网上的图(如果侵权,请联系我,我会第一时间删除)
此图说明了一个jvm中(一个进程中)所拥有的资源。而JNI就是用来实现调用本地方法的一种方法。而这些本地方法有两种方式可以被注册到jvm中,分别如下:
说明:通过特定的函数命名方式(包名类名函数名)(若以上命名中含有_,将会通过在其后加一位数字方式来标识)来注册。当在java层调用System.loadLibrary,jvm会遍历这个so库的所有合法的方法,并放到本地方法栈,以供使用。
缺点:
1 初次call本地函数时,需要先在jni下去搜索相关的jni函数,然后建立jni函数和native函数关系,导致效率降低
2 使用规则复杂,不利于开发(不方便)。
说明:
1 JNINativeMethod保存Java Native函数和JNI函数的对应关系
2 Java层中调用System.loadLibrary加载so库,并调用JNI_OnLoad开始注册
3 JNI_OnLoad中调用AndroidRuntime::registerNativeMethods
4 AndroidRuntime::registerNativeMethods中调用 jniRegisterNativeMethods
注意:这里有个知识叫做java签名,此签名是指的方法的类型标识,也就是一堆类型简写。(写法:(函数参数列表)返回值)
下列是常用的类型总结(资料来于网上,若有侵权,请联系我,我第一时间删除):
所有结果的最终效果如图:
#PS:请尊重原创,不喜勿喷
#PS:要转载请注明出处,本人版权所有.
有问题请留言,看到后我会第一时间回复
#PS:这个只是 《 我自己 》理解,如果和你的
#原则相冲突,请谅解,勿喷
由于最近重新接触了部分Android相关的东西,对一些需要混合编程的手段做了整理,同时也对Java中常见的反射技术进行归纳总结。(本文适合知道JNI和反射是什么鬼的人阅读)(可变参数实现在JNI部分的IoctlGpio方法)
JNI部分
Java native interface(java本地调用接口)主要是实现C或者C++和java交互。先来看一张来至于网上的图(如果侵权,请联系我,我会第一时间删除)
此图说明了一个jvm中(一个进程中)所拥有的资源。而JNI就是用来实现调用本地方法的一种方法。而这些本地方法有两种方式可以被注册到jvm中,分别如下:
JNI之静态注册
public class Operate_Gpio { public native int IoctlGpio(int cmd, String ...arg); public native int IoctlGpio(int cmd, int ...arg); //java static code static { System.loadLibrary("OperateGpio"); } } //call IoctlGpio() Operate_Gpio op_gpio = new Operate_Gpio(); op_gpio.IoctlGpio(2,1,3); op_gpio.IoctlGpio(2,"a","b");
extern "C" JNIEXPORT jint JNICALL Java_JNI_Operate_1Gpio_IoctlGpio(JNIEnv *env, jobject instance, jint cmd,jobjectArray arg) { jboolean iscopy; switch (cmd) { case 1: { jint *arg1 = env->GetIntArrayElements((jintArray) arg, 0); NativeLog(env, instance, 'D', "Test string arg1", Int_to_String(arg1[0])); NativeLog(env, instance, 'D', "Test string arg2", Int_to_String(arg1[1])); env->ReleaseIntArrayElements((jintArray)arg, arg1, 0); break; } case 2: { jstring arg3 = (jstring) env->GetObjectArrayElement(arg, 0); jstring arg4 = (jstring) env->GetObjectArrayElement(arg, 1); NativeLog(env, instance, 'D', "Test string arg3", env->GetStringUTFChars(arg3, &iscopy)); NativeLog(env, instance, 'D', "Test string arg4", env->GetStringUTFChars(arg4, &iscopy)); break; } default:{ break; } } return 0; }
说明:通过特定的函数命名方式(包名类名函数名)(若以上命名中含有_,将会通过在其后加一位数字方式来标识)来注册。当在java层调用System.loadLibrary,jvm会遍历这个so库的所有合法的方法,并放到本地方法栈,以供使用。
缺点:
1 初次call本地函数时,需要先在jni下去搜索相关的jni函数,然后建立jni函数和native函数关系,导致效率降低
2 使用规则复杂,不利于开发(不方便)。
JNI之动态注册
public class Operate_Gpio { public native int TestGpio(); //java static code static { System.loadLibrary("OperateGpio"); } } Operate_Gpio op_gpio = new Operate_Gpio(); op_gpio.TestGpio();
/** * Table of methods associated with a single class. */ /* * * typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod; * */ // 结构体,分别是java层的函数名称,签名,对应的函数指针 static JNINativeMethod gMethods[] = { { "TestGpio", "()I", (void*)TestGpio },//绑定 }; static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; if ( vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return -1; } assert(env != NULL); if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) return -1; /* success -- return valid version number */ return JNI_VERSION_1_4; }
说明:
1 JNINativeMethod保存Java Native函数和JNI函数的对应关系
2 Java层中调用System.loadLibrary加载so库,并调用JNI_OnLoad开始注册
3 JNI_OnLoad中调用AndroidRuntime::registerNativeMethods
4 AndroidRuntime::registerNativeMethods中调用 jniRegisterNativeMethods
注意:这里有个知识叫做java签名,此签名是指的方法的类型标识,也就是一堆类型简写。(写法:(函数参数列表)返回值)
下列是常用的类型总结(资料来于网上,若有侵权,请联系我,我第一时间删除):
/* Java方法签名中特殊字符/字母含义 特殊字符 数据类型 特殊说明 V void 一般用于表示方法的返回值 Z boolean B byte C char S short I int J long F float D double [ 数组 以[开头,配合其他的特殊字符,表示对应数据类型的数组,几个[表示几维数组 L全类名; 引用类型 以L开头、;结尾,中间是引用类型的全类名 */
反射部分
程序运行时获取类的属性,也可调用类的方法。可灵活的方便构建出各种复杂的逻辑结构。C或者C++层反射
int static NativeLog(JNIEnv *env, jobject instance ,char type, std::string tag, std::string msg){ jclass clazz = env->FindClass("android/util/Log") ; jmethodID jmth_id; switch (type){ case 'V': jmth_id = env->GetStaticMethodID(clazz, "v", "(Ljava/lang/String;Ljava/lang/String;)I"); break; case 'D': jmth_id = env->GetStaticMethodID(clazz, "d", "(Ljava/lang/String;Ljava/lang/String;)I"); break; case 'I': jmth_id = env->GetStaticMethodID(clazz, "i", "(Ljava/lang/String;Ljava/lang/String;)I"); break; case 'W': jmth_id = env->GetStaticMethodID(clazz, "w", "(Ljava/lang/String;Ljava/lang/String;)I"); break; case 'E': jmth_id = env->GetStaticMethodID(clazz, "e", "(Ljava/lang/String;Ljava/lang/String;)I"); break; default: break; } return env->CallStaticIntMethod(clazz, jmth_id, env->NewStringUTF(tag.c_str()), env->NewStringUTF(msg.c_str())); } extern "C" JNIEXPORT jint JNICALL Java_JNI_Operate_1Gpio_OpenGpio(JNIEnv * env, jobject obj){ //open devices ... ... NativeLog(env, obj, 'D', "Test", "Reflect test."); return 0; }
public class Operate_Gpio { public native int OpenGpio(); // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("OperateGpio"); } } Operate_Gpio op_gpio = new Operate_Gpio(); op_gpio.OpenGpio();
JAVA层反射
try { Class clazz = Class.forName("android.util.Log"); Method method = clazz.getDeclaredMethod("d", String.class, String.class); method.invoke(null,"Test","Fuck");//调用静态函数 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
所有结果的最终效果如图:
#PS:请尊重原创,不喜勿喷
#PS:要转载请注明出处,本人版权所有.
有问题请留言,看到后我会第一时间回复
相关文章推荐
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- 利用Java的反射、泛型以及动态参数实现JDBC工具类
- [Android]JNI动态注册Java函数教程
- 黑马程序员_Java高新技术(静态导入、可变参数、增强for循环、自动拆装箱、枚举、反射)
- 【Java反射学习笔记系列之jdk动态代理】静态代理和动态代理的区别以及动态代理的作用和实现
- Android深入理解JNI(一)JNI原理与静态、动态注册
- Android JNI动态注册Native 方法(实现IDA中改名)
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- JavaSE JNI 动态注册本地方法(c语言实现native层)
- Android JNI编程和NDK学习 --静态、动态两种方式实现JNI
- Android JNI反射调用Java构造方法、成员方法和静态方法
- Android jni 静态注册 和动态注册
- Android深入理解JNI(一)JNI原理与静态、动态注册
- Android深入理解JNI(一)JNI原理与静态、动态注册
- Android 第十九课 大喇叭--广播机制----动态注册监听网络变化与静态注册实现开机启动
- Android JNI开发(1)--JavaVM和 JNIEnv 动态注册本地方法
- Android JNI编程和NDK学习 --静态、动态两种方式实现JNI
- Android使用JNI实现Java与C之间传递数据
- 利用JAVA的动态属性之反射原理实现一个简单AOP容器 - AOP的实现原理分析
- Java数组反射实现动态的判断一个对象书否是数组,并且对数组进行拆包输出 。。