博客
关于我
JNI签名及深入理解JNI,JNI中的反射 - android
阅读量:81 次
发布时间:2019-02-26

本文共 3711 字,大约阅读时间需要 12 分钟。

JNI开发指南:方法签名与反射调用Java方法

JNI(Java Native Interface)是一种允许Java程序与本地编程语言(如C/C++)交互的机制,广泛应用于Android开发中。通过JNI,Java程序能够调用本地编写的函数,反之,本地程序也能调用Java层的函数,实现两层语言的互通。以下将详细介绍JNI中的方法签名以及如何通过C反射调用Java方法。


方法签名:唯一标识Java方法

Java支持方法重载(overloading),这意味着即使函数名相同,参数类型也可能不同。因此,仅凭方法名无法唯一确定一个方法。为了解决这个问题,JNI引入了方法签名,通过唯一的签名字符串标识每个Java方法。

方法签名的组成规则

  • 基本类型:每种基本数据类型对应一个单字符签名。
  • 数组:数组类型签名以[开头,后跟元素类型的签名。
  • :类的签名格式为L<全限定类名>;,全限定类名中用/替代._
  • 函数签名:格式为(参数类型签名列表)返回值类型签名,参数类型和返回值类型的签名连在一起,之间无空格。
  • 例如:

    • Java方法 void func() 的签名为 ()V
    • Java方法 int func(boolean a) 的签名为 (Z)I

    C反射调用Java方法

    通过JNI,可以在C/C++程序中反射调用Java方法。这种技术通常用于Android开发中,实现本地程序与Java程序的互动。以下是实现C反射调用Java方法的关键步骤:

    1. 获取Java类的JNI引用

    在C/C++代码中,使用JNIEnvAPI获取Java类的引用:

    jobject obj = NewObject("com.example.MyClass", "staticmethod");

    2. 调用Java成员方法

    通过JNIEnvCallObjectMethod函数调用Java成员方法:

    jint result = JNIEnv_CallObjectMethod(env, obj, methodID, argsArray, argCount);

    3. 调用Java静态方法

    调用Java静态方法的方法类似于成员方法,但不需要传递this对象:

    jint result = JNIEnv_CallStaticMethod(env, classID, methodID, argsArray, argCount);

    4. 调用Java构造方法

    通过JNIEnv反射调用Java构造方法,需要传递构造函数的参数:

    jint result = JNIEnv_ReflectConstruct(env, classID, methodID, argsArray, argCount);

    方法签名生成器工具

    为了简化Java方法签名的生成过程,可以开发一个工具类。以下是一个简单的Java代码示例:

    public class SignatureGen {
    private static HashMap
    primitives = new HashMap
    () {
    {
    put(Void.class.getName(), "V");
    put(Boolean.class.getName(), "Z");
    put(Byte.class.getName(), "B");
    put(Character.class.getName(), "C");
    put(Short.class.getName(), "S");
    put(Integer.class.getName(), "I");
    put(Long.class.getName(), "J");
    put(Float.class.getName(), "F");
    put(Double.class.getName(), "D");
    }
    };
    public static String getSignature(Class ret, Class... params) {
    StringBuilder builder = new StringBuilder();
    builder.append("(");
    for (Class param : params) {
    builder.append(getSignature(param));
    }
    builder.append(")");
    builder.append(getSignature(ret));
    return builder.toString();
    }
    private static String getSignature(Class param) {
    StringBuilder builder = new StringBuilder();
    if (param.isArray()) {
    String componentType = param.getComponentType().getName();
    builder.append("[").append(primitives.get(componentType)).append(")");
    } else {
    String typeName = param.getName();
    if (primitives.containsKey(typeName)) {
    builder.append(primitives.get(typeName));
    } else {
    builder.append("L").append(typeName.replace(".", "/")).append(";");
    }
    }
    return builder.toString();
    }
    }

    使用示例

    // 调用 Void 类的方法
    Log.d("Signature", "void func() -> " + SignatureGen.getSignature(Void.class));
    // 调用 Boolean 类的方法
    Log.d("Signature", "boolean func() -> " + SignatureGen.getSignature(Boolean.class));
    // 调用 Integer 类的方法,参数为 Boolean 类型
    Log.d("Signature", "int func(boolean a) -> " + SignatureGen.getSignature(Integer.class, Boolean.class));
    // 调用 Integer 类的方法,参数为 Boolean 和 String 类型
    Log.d("Signature", "int func(boolean a, String b) -> " + SignatureGen.getSignature(Integer.class, Boolean.class, String.class));
    // 调用 Integer 类的方法,参数为 Byte 数组
    Log.d("Signature", "int func(byte[] c) -> " + SignatureGen.getSignature(Integer.class, Byte[].class));
    // 调用 Long 类的方法,参数为 Integer、String 和 Integer 数组
    Log.d("Signature", "long func(int n, String str, int[] arr) -> " + SignatureGen.getSignature(Long.class, Integer.class, String.class, Integer[].class));

    总结

    通过JNI,我们能够在C/C++程序中与Java方法进行交互。方法签名是实现Java方法调用唯一性的关键,而反射机制则提供了调用Java类成员、静态方法和构造方法的功能。通过合理使用方法签名和反射机制,我们可以实现Java与本地程序的高效交互。

    转载地址:http://ptyk.baihongyu.com/

    你可能感兴趣的文章
    NI笔试——大数加法
    查看>>
    NLog 自定义字段 写入 oracle
    查看>>
    NLog类库使用探索——详解配置
    查看>>
    NLP 基于kashgari和BERT实现中文命名实体识别(NER)
    查看>>
    NLP 模型中的偏差和公平性检测
    查看>>
    Vue3.0 性能提升主要是通过哪几方面体现的?
    查看>>
    NLP 项目:维基百科文章爬虫和分类【01】 - 语料库阅读器
    查看>>
    NLP_什么是统计语言模型_条件概率的链式法则_n元统计语言模型_马尔科夫链_数据稀疏(出现了词库中没有的词)_统计语言模型的平滑策略---人工智能工作笔记0035
    查看>>
    NLP三大特征抽取器:CNN、RNN与Transformer全面解析
    查看>>
    NLP学习笔记:使用 Python 进行NLTK
    查看>>
    NLP度量指标BELU真的完美么?
    查看>>
    NLP的不同研究领域和最新发展的概述
    查看>>
    NLP的神经网络训练的新模式
    查看>>
    NLP采用Bert进行简单文本情感分类
    查看>>
    NLP问答系统:使用 Deepset SQUAD 和 SQuAD v2 度量评估
    查看>>
    NLP项目:维基百科文章爬虫和分类【02】 - 语料库转换管道
    查看>>
    NLP:使用 SciKit Learn 的文本矢量化方法
    查看>>
    nmap 使用方法详细介绍
    查看>>
    Nmap扫描教程之Nmap基础知识
    查看>>
    nmap指纹识别要点以及又快又准之方法
    查看>>