JNI C反射调用java方法
前面记录了调用C的学习笔记,现在来记录一下C反射调用Java的笔记。
JNI开发学习之调用C方法
Android开发中调用一个类中没有公开的方法,可以进行反射调用,而JNI开发中C调用java的方法也是反射调用。
C代码回调Java方法步骤:
①获取字节码对象(jclass (FindClass)(JNIEnv, const char*);)
②通过字节码对象找到方法对象(jmethodID (GetMethodID)(JNIEnv, jclass, const char, const char);)
④通过对象调用方法,可以调用空参数方法,也可以调用有参数方法,并且将参数通过调用的方法传入(void (CallVoidMethod)(JNIEnv, jobject, jmethodID, ...);)
首先,也是按照前面的步骤新建一个 import C++ 工程,新建ccalljava.c 和一个JNI.java文件(别忘了修改CMakeLists.txt对应C方法的名字和路径)

JNI.java中编写本地方法:
//C调用java空方法
public native void callbackmethod();
//C调用java中的带两个int参数的方法
public native void callbackIntmethod();
//C调用java中参数为string的方法
public native void callbackStringmethod();
//C调用java中静态方法
public native void callStaticmethod();
并且编写被C反调的java方法:
//C调用java空方法
public void helloFromJava(){
Toast.makeText(context, "C调用了java的空方法",Toast.LENGTH_SHORT ).show();}
//C调用java中的带两个int参数的方法
public int add(int x,int y) {
return x+y;}
//C调用java中参数为string的方法
public void printString(String s){
Toast.makeText(context, s, Toast.LENGTH_SHORT).show();}
//C调用java中静态方法
public static void staticmethod(String s){
Log.w("毛麒添",s+",我是被C调用的静态方法");}
下面来编写ccalljava.c中的C方法
/**C函数反射调用java中的空方法 */
JNIEXPORT void JNICALLJava_com_mao_ccalljava_JNI_callbackmethod(JNIEnv *env, jobject object) {
jclass jclazz = (*env)->FindClass(env, "com/mao/ccalljava/JNI");
jmethodID methodID = (*env)->GetMethodID(env, jclazz, "helloFromJava", "()V");
(*env)->CallVoidMethod(env,object,methodID);}
/**
调用java中Int方法
*/
JNIEXPORT void JNICALLJava_com_mao_ccalljava_JNI_callbackIntmethod(JNIEnv *env, jobject object) {
jclass clzz=(*env)->FindClass(env,"com/mao/ccalljava/JNI");
jmethodID methodID=(*env)->GetMethodID(env,clzz,"add","(II)I");
int result=(*env)->CallIntMethod(env,object,methodID,,);
//logcat 打印相加返回的结果
LOGD("RESLUT = %d",result);
}
/**
调用java中String方法
*/
JNIEXPORT void JNICALLJava_com_mao_ccalljava_JNI_callbackStringmethod(JNIEnv *env, jobject object) {
//先获取字节码对象 jclass (*FindClass)(JNIEnv*, const char*);
jclass clzz=(*env)->FindClass(env,"com/mao/ccalljava/JNI");
//获取method对象 jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodID=(*env)->GetMethodID(env,clzz,"printString","(Ljava/lang/String;)V");
//将要传递的字符串先转换成jstring类型 ,然后在传递给java方法 int result=(*env)->NewStringUTF(env,"hello form C/C++ "); (*env)->CallVoidMethod(env,object,methodID,result);
}
/**
调用Java中的静态方
*/
JNIEXPORT void JNICALLJava_com_mao_ccalljava_JNI_callStaticmethod(JNIEnv *env, jobject instance) {
jclass clzz=(*env)->FindClass(env,"com/mao/ccalljava/JNI");
jmethodID methodID=(*env)->GetStaticMethodID(env,clzz,"staticmethod","(Ljava/lang/String;)V");
jstring str = (*env)->NewStringUTF(env, "C调用java");
(*env)->CallStaticVoidMethod(env,clzz,methodID,str);
}
通过字节码对象找到方法对象,该方法中的第四个参数是方法签名
jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
获取方法签名的方法是进入工程目的 ..../build/classes/debug 进入控制台,
输入命令 javap -s 要获取方法的路径(例如本例 javap -s com.mao.ccalljava.JNI)


上面步骤二中提到的没有生命周期的解决方法:
报空指针,主要就是没上下文环境,反射调用的方法是new出来的,也会没有生命周期.这时候就可以将本地方法和调用的方法都放在同一个类中,没有上下文环境就在创建方法的时候在构造方法中接收一个。
private Context context;
public JNI(Context context){
this.context=context;
}
最后,别忘了添加在JNI.java中添加动态链接库文件(布局和MianActiivty中逻辑比较简单,这里
static {
System.loadLibrary("ccalljava");
}
在gradle 配置一些处理器架构
externalNativeBuild {
cmake {
cppFlags ""
// Clang是一个C语言、Objective-C、C++语言的轻量级编译器。
arguments "-DANDROID_TOOLCHAIN=clang"
// 生成.so库的目标平台
abiFilters "armeabi-v7a" , "armeabi" ,"x86"
}
}
接下来在工程编译通过后可以该目录下找到不同处理器架构的动态链接库文件

最后,上几张运行成功的截图:


JNI C反射调用java方法的更多相关文章
- JNI中C调用Java方法
背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...
- Android JNI中C调用Java方法
背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...
- 对JAVA Bean使用PropertyDescriptor反射调用JAVA方法低耦合
对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. public void g ...
- 对JAVA Bean使用PropertyDescriptor反射调用JAVA方法
对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. 示比例如以下: NonCo ...
- HAL中通过JNI调用java方法【转】
转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...
- cocos2d-x中使用JNI的调用JAVA方法
用cocos2d-x公布Android项目时.都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface).JNI是JAVA的一个通用接口.旨在本地化 ...
- Android Studio NDK开发-JNI调用Java方法
相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需 ...
- java动态载入指定的类或者jar包反射调用其方法
序言 有时候.项目中会用到java动态载入指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大减少,更加的模块化.代码利用率更高.模式中的代理模式就用到java的这一机制. 下 ...
- java native interface JNI 调用Java方法
在上一篇文章中介绍了JNI.以及java调用JNI.这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你能够创建Java对象,get.set 静态(static)和 实例(instanc ...
随机推荐
- 毕业不到一年,绩效打了个D!
周末了,和大家来聊聊程序员工作态度的问题. 说说栈长的事迹吧,这是好多年前的事了,那时候,栈长才毕业不到一年,那次绩效打了个D!事后,我很气愤啊,我那时还在博客上写文章怒骂了部门经理,现在想起来,真是 ...
- SpringMvc + socket.io + vue + vue-socket.io实例
SpringMvc部分实现 1. 所需依赖 <dependency> <groupId>com.corundumstudio.socketio</g ...
- Linux常用命令之压缩和解压缩命令
目录 1.压缩解压缩格式 .gz 一.将文件压缩为 .gz 格式,只能压缩文件:gzip 二.将 .gz 文件解压:gunzip 2.压缩解压缩格式 .tar.gz 一.将文件或目录压缩为 .tar. ...
- SpringMVC学习(二)———— 参数绑定
一.参数绑定 1.1.什么是参数绑定? 客户在浏览器端会提交一些参数到服务器端,比如用户的登录等,就会传username 和 password过来,springmvc则通过参数绑定组件将请求参数的内容 ...
- [转]如何将高版本的SQL Server数据库备份到低版本的SQL Server
本文转自:https://blog.csdn.net/wang465745776/article/details/54969676 前提条件备份SQL Server服务器版本为:12.0.2000.8 ...
- Python GUI
1.flexx Flexx 是一个纯Python工具包,用来创建图形化界面应用程序.其使用 Web 技术进行界面的渲染.你可以用Flexx来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档 ...
- C#调用存储过程执行缓慢,但在数据库中执行却很快的问题
参考: http://www.debugease.com/mssqlbasic/976568.html https://www.cnblogs.com/Irving/p/3951220.html ht ...
- 使用wubi安装ubuntu14.04出现的常见错误的解决办法
花了一天的时间终于安装上了Ubuntu14.04,过程坎坷,是血泪史,开始报“cannot download the metalink and therefore the ISO”错误,解决后,又报“ ...
- springMVC_05结果跳转方式
一.总结 总共有四个, 1.设置ModelAndView的值,根据view和视图解析器跳转到指定的页面 2.通过servletapi对象来实现,不需要视图解析器 3.通过springmvc来实现转发和 ...
- Elasticsearch系列(2):安装Elasticsearch(Linux环境)
系统环境 操作系统:CentOS 6.9 Elasticsearch:6.2.2 Filebeat:6.2.2(收集IIS日志) Kibana:6.2.2 Java:Java 8 注意:elk最好选择 ...