• Android_JNI编程入门


    最权威的文档请见JNI

    一、JNI概述

      在某些情况下,单独使用Java编程无法满足开发者的需求,这时可以使用JNI(Java Native Interface)来处理。常见的需要使用JNI的场景有:

    (1)标准Java类库不支持应用程序所需的平台相关特性。
    (2)存在其他语言编写的库,并且希望通过JNI使Java代码能够使用该库。
    (3)用低级语言(如汇编)实现一小部分时间关键型代码。

      通过JNI编程,可以使用native methods做到:

    (1)创建、检查和更新Java对象(包括数组和字符串)。
    (2)调用Java方法。
    (3)捕获并抛出异常。
    (4)加载类并获取类信息。
    (5)执行运行时类型检查。

    二、JNI类型对应

    2.1 基础类型

    在这里插入图片描述

    2.2 引用类型

    在这里插入图片描述
    在C++中:

    class _jobject {};
    class _jclass : public _jobject {};
    // ...
    typedef _jobject *jobject;
    typedef _jclass *jclass;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.3 值类型

    typedef union jvalue {
        jboolean z;
        jbyte    b;
        jchar    c;
        jshort   s;
        jint     i;
        jlong    j;
        jfloat   f;
        jdouble  d;
        jobject  l;
    } jvalue;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.4 类型签名

    在这里插入图片描述
    对于以下Java方法:

    long f (int n, String s, int[] arr);
    
    • 1

    具有如下签名(signature):

    (ILjava/lang/String;[I)J
    
    • 1

    三、JNI函数操作

    JNI方法列表请见:Interface Function Table

    (1)其中有对象操作方法如:

    jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
    
    • 1

    其中参数:
    env: JNI 接口指针,不能为null
    clazz: Java类对象的引用,不能为null
    methodID: 构造函数的MethodID,可以通过GetMethodID()获得

    (2)其中有对象Fileld 访问方法如:

    jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
    
    • 1

    其中参数:
    env: JNI 接口指针,不能为null
    clazz: Java类对象,不能为null
    name: 字段名的UTF-8 string, 不能为null
    sig: 字段签名的UTF-8 string, 不能为null

    …方法较多就不再继续罗列。

    四、native方法注册

    JVM有两种方法来查找native方法并将其与Java代码链接。第一种方法是以特定的命名方式命名native 函数,以便JVM能够找到它。另一种方法是使用JNI RegisterNatives()方法,RegisterNatives()使用作为参数传递的类注册本机方法。通过使用这种方法,我们可以随意命名C++函数。java.lang.Object的registerNatives()方法使用了第二种方法。让我们看看C语言中OpenJDK 8中java.lang.Object的registerNatives()方法实现:

    static JNINativeMethod methods[] = {
        {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
        {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
        {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
        {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
        {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
    };
    
    JNIEXPORT void JNICALL
    Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
    {
        (*env)->RegisterNatives(env, cls,
                                methods, sizeof(methods)/sizeof(methods[0]));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    五、使用JNI例子

    public class RegisterNativesHelloWorldJNI {
    
        public native void register();
        public native String sayHello();
    
        public static void main(String[] args) {
            RegisterNativesHelloWorldJNI helloWorldJNI = new RegisterNativesHelloWorldJNI();
            helloWorldJNI.register();
            helloWorldJNI.sayHello();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    //c++注册实现
    static JNINativeMethod methods[] = {
      {"sayHello", "()Ljava/lang/String;", (void*) &hello },
    };
    
    JNIEXPORT void JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_register (JNIEnv* env, jobject thsObject) {
        jclass clazz = env->FindClass("com/baeldung/jni/RegisterNativesHelloWorldJNI");
    
        (env)->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(methods[0]));
    }
    
    JNIEXPORT jstring JNICALL hello (JNIEnv* env, jobject thisObject) {
        std::string hello = "Hello from registered native C++ !!";
        std::cout << hello << std::endl;
        return env->NewStringUTF(hello.c_str());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    打印:

    Hello from registered native C++ !!
    
    • 1
  • 相关阅读:
    Linux-2-进程
    力扣记录:动态规划3打家劫舍——198 打家劫舍,213 打家劫舍II,337 打家劫舍III
    12、建立健全人员培训体系
    【Vue】实现商品列表的无限加载
    c# 反射
    Redis关闭持久化
    HotSpot垃圾算法实现之枚举根节点和安全点安全区域
    机器学习之SGD, Batch, and Mini Batch的简单介绍
    Node.js入门指南(一)
    308场周赛 leetcode xp_xht123
  • 原文地址:https://blog.csdn.net/weixin_44277699/article/details/126375536