• AndroidNDK JNI中调用java方法


    这次在做NDK开发的时候,有需求需要在JNI直接调用和获取Java中的方法和变量,比如回调,系统信息参数等…
    在JNI中调用Java方法,就需要使用FindClassGetMethodID这两个类

    使用FindClass和GetMethodID调用Java方法

    先上一个简单调用Java方法的例子:
    我们有一个数学工具类包名是com.andy.obj,里面有一个加法的静态方法和一个减法的普通方法,

    import com.andy.obj;
    
    public class MathUtil {
    	public static int add(int a, int b) {
    		return a+b;
    	}
    	
    	public int reduce(int a,int b) {
    		return a-b;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    首先在JNI中可以通过FindClass可以找到Java类,得到jclass,例如:

    jclass javaclass = env->FindClass("com/andy/obj/MathUtil");
    
    • 1

    FindClass的参数需要传入类的完整包名。

    使用GetMethodID可以获取类的方法,得到jmethodID,例如:

    jmethodID jstaticmethodIds = env->GetMethodID(javaclass, "add", "(II)I");
    jmethodID jmethodIds = env->GetMethodID(javaclass, "reduce", "(II)I");
    
    • 1
    • 2

    其中第四个参数是比较奇怪的字符串,这就是方法签名,现在只需要知道是设置了Java原生方法的两个int类型的参数和一个int类型的返回值,具体用法和作用后面细讲

    调用Java方法
     //调用静态方法
     env->CallStaticObjectMethod(javaclass, jstaticmethodIds, 1,1);
     jobject object = env->AllocObject(jclazz);
     //调用普通方法
     env->.CallIntMethod(javaclass, jmethodIds, 1,1);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上总流程

    extern "C"
    JNIEXPORT void JNICALL
    Java_com_andy_obj_test_add(JNIEnv *env, jobject jobj) {
        //得到字节码
        jclass javaclass = env->FindClass("com/andy/obj/MathUtil");
        //得到普通方法
        jmethodID jmethodIds = env->GetMethodID(jclazz,"reduce","(II)I");
        //得到静态普通方法
        jmethodID jstaticmethodIds = env->GetStaticMethodID(jclazz,"add","(II)I");
    	//调用静态方法
    	env->CallStaticObjectMethod(env, javaclass, jstaticmethodIds,1,1);
        //调用普通方法需要实例化
        jobject object = env->AllocObject(jclazz);
        //调用普通方法
        env->CallIntMethod(object,jmethodIds,100,1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    方法签名

    GetMethodID中第四个参数()V就是方法签名,Java是支持重载的,所以需要标明方法的传参和返回值,这就是方法的签名。它是用来保证方法的唯一性。其中()代表不传参数,V代表返回值为void。
    方法签名对于Java的类型都有一一对应的值。方法签名中用大写的字母对应了java的基本数据类型:

    • Z -> boolean
    • B -> byte
    • C -> char
    • S -> short
    • I -> int
    • J -> long
    • F -> float
    • D -> double

    其实就是有两个比较特殊的:boolean对应的是Z,long对应的J,其他的都是首个字母的大写即可。

    数组的表示方法,以[为标志,一个[标识一维数组,[[表示二维数组,例如:

    • byte[] -> [B
    • int[][] -> [[I

    引用类型的表示方法,需要以L开头,以;结束,中间对应类型的包名加类名,例如:

    • String -> Ljava/lang/String;
    • Object -> Ljava/lang/Object;

    自定义类的表示方法类似,比如包名为com.andy.obj,类名为MethodBean的表示方法是:

    • com.andy.obj.MethodBean ->Lcom.andy.obj.MethodBean;
  • 相关阅读:
    Norgen提取试剂盒丨血浆/血清循环和核外RNA提取试剂盒
    并查集の进阶用法
    Python之ini配置文件详解
    Halcon我的基础教程(一)(我的菜鸟教程笔记)-halcon仿射变换(Affine Transformation)的探究与学习
    旅游攻略APP外包开发功能
    C++ std::hash 获得字符串哈希值
    ASP.NET Core知识之RabbitMQ组件使用(二)
    [C++基础]-类和对象(中~万字详解)
    【Python】深入解析Python中的eval()函数
    on java8之封装
  • 原文地址:https://blog.csdn.net/weixin_40303382/article/details/128037882