Jni中还可以采用RegisterNatives来注册jni的方法,注册以后的jni函数的命名可以不需要符合类似javah命令生成的函数的规则

RegisterNatives为JNIEnv的成员函数,声明为:
    jint (JNICALL *RegisterNatives) (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,jint nMethods);

其对应的取消注册的函数为声明为:
    jint (JNICALL *UnregisterNatives) (JNIEnv *env, jclass clazz);

在java中调用System.loadLibrary("somelib");的时候,系统会自动调用jni的函数JNI_OnLoad,
在程序退出的时候,系统卸载“somelib”,会自动调用jni的函数JNI_OnUnload,
所以我们需要在jni的接口文件中重写这两个函数

以上一篇建立的HelloJni的例子来说明:
先定义一个字符串,内容为类名const char* JNIT_CLASS = "com/example/hellojni/HelloJni";

再定义一个函数的说明的数组

static JNINativeMethod gMethods[] = {
        {"stringFromJNI", "()Ljava/lang/String;",(void*)stringFromJNI},
};

JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
    JNIEnv *env = NULL;
    if ((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4)){
        return JNI_ERR;
    }

jclass cls = (*env)->FindClass(env, JNIT_CLASS);
    if (cls == NULL)
    {
        return JNI_ERR;
    }
    jint nRes = (*env)->RegisterNatives(env, cls, gMethods, sizeof(gMethods)/sizeof(gMethods[0]));
    if (nRes < 0)
    {
        return JNI_ERR;
    }
    return JNI_VERSION_1_4;
}

JNIEXPORT void JNICALL
JNI_OnUnLoad(JavaVM *jvm, void *reserved)
{
    JNIEnv *env = NULL;
    if ((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4)){
        return;
    }
    jclass cls = (*env)->FindClass(env, JNIT_CLASS);
    if (cls == NULL)
    {
        return;
    }
    jint nRes = (*env)->UnregisterNatives(env, cls);
    return;
}

其中JNIT_CLASS 表示的是要调用jni的java类的名称
gMethods[]为RegisterNatives的第三个函数,表示的是所有jni的函数的集合。

JNINativeMethod是表示jni方法的结构体,其结构如下:
typedef struct {
    
     char *name;
     char *signature;
      void *fnPtr;

} JNINativeMethod;

第一个变量name为java类中native函数的名称,
第二个变量signature为java类中native函数的java类型描述,
第三个变量fnPtr为jni中对应的函数名称,格式为类似(void*)MethodName,

函数和变量的java类型描述可以通过命令 javap -s -p classname来获得,classname与使用javah时写的名称一致,javah生成的头文件的每个函数的注释中也有这个描述

对于“()Ljava/lang/String;”一个描述,表示该函数没有参数,返回值为String。括号内的是参数列表,后面跟的是返回值

java中简单类型和jni中的描述的对应关系如下表所示:

Field Descriptor Java Language Type
Z boolean
B byte
C char
S short
I int
J long
F float
D double

对于复杂类型,字符串描述以“L”开头,以“;”结束,例如java中的 String ,在jni中的描述为"Ljava/lang/String;"

对于数组,以“[”开头,接类型描述,例如int[ ],在jni中的描述为“[I”;String[ ], 对应为“[Ljava/lang/String;”;如果是数组维数增加一维,则"["增加一个,例如int[ ][ ],对应为“[[I”;

以上内容具体参见《The Java™ Native  Interface   Programmer’s Guide and Specification》一书,JNI中使用的各类型参见第12章 JNI TYPE

在使用JNI_OnLoad之时,我们不能把classname传递给jni,所以const char* JNIT_CLASS 是一个固定的名称,我们在生成SO文件的同时这个classname就固定下来了,所以,当提供so文件的同时,需要提供一个调用该so文件的java文件,类似c++中提供dll时需要提供的.h文件一样。

android — JNI注册方法说明的更多相关文章

  1. Android JNI使用方法

    经过几天的努力终于搞定了android JNI部分,下面将我的这个小程序和大家分享一下.android JNI是连接android Java部分和C/C++部分的纽带,完整使用JNI需要Java代码和 ...

  2. Android JNI和NDK学习(04)--NDK调试方法(转)

    本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092812.html 本文主要介绍在ndk中添加log的方法.然后,我们就可 ...

  3. Android JNI的使用方法

    1.JNI是什么 JNI是Java Native Interface的缩写,它提供若干的API实现Java与其他语言之间的通信.而Android Framework由基于Java语言的的Java层与基 ...

  4. android JNI常用添加log方法

    android JNI 打log方法 添加库支持 LOCAL_LDLIBS :=-llog -landroid 包含头文件 #include <android/log.h> #define ...

  5. Android jni 编程(参数的传递,成员,方法的)相互访问

    package com.test.androidjni; import android.app.Activity; import android.os.Bundle; import android.u ...

  6. Android Market google play store帐号注册方法流程 及发布应用注意事项

    Android Market google play store帐号申请 注册方法流程 在 Google Play 中发布软件之前,您需要完成以下三项工作: 创建开发人员个人资料 接受开发人员分发协议 ...

  7. Android调用JNI本地方法跟踪目标代码

    正如Android调用JNI本地方法经过有点改变章所说跟踪代码是可行的,但是跟踪某些代码会出现anr,点击取消,还是不好运,有提高办法吗?回答是有(gdb还没试过,本文只讨论ida). 下面是我使用  ...

  8. Android Market google play store帐号注册方法流程 及发布应用注意事项【转载】

    [转载]http://www.cnblogs.com/zdz8207/archive/2012/07/09/google-play-store-registered.html Android Mark ...

  9. Android JNI 学习(四):接口方法表 & Base Api & Exception Api

    本文我们来总结一下JNI 提供的功能列表及相关的函数表. 注意:请注意使用术语“必须”来描述对JNI程序员的限制.例如,当您看到某个JNI函数必须接收非NULL对象时,您有责任确保不将NULL传递给该 ...

随机推荐

  1. Replication--进程无法在“xxxx”上执行“sp_replcmds”

    错误消息:进程无法在“xxxx”上执行“sp_replcmds”. (源: MSSQL_REPL,错误号: MSSQL_REPL20011)获取帮助: http://help/MSSQL_REPL20 ...

  2. 运维必备:Oracle自备份精简教程(linux及win)

    Oracle在linux环境下的自动备份 1.自动导出及历史文件删除脚本 su - oracle<<EOF cd /db_backup/databak mv orabak*.* /db_b ...

  3. php 数组操作符

    1.数组操作符 数组运算符 例子 名称 结果 $a + $b 联合 $a 和 $b 的联合. $a == $b 相等 如果 $a 和 $b 具有相同的键/值对则为 TRUE. $a === $b 全等 ...

  4. python 多线程 paramiko实现批量命令输入输出

    远程批量执行命令 实现多线程执行 速度快 实现多并发登录 #-*- coding: utf-8 -*- #!/usr/bin/python import paramiko import threadi ...

  5. URL设置问题

    URL设置那里删除了<item path="index.aspx" pattern="index.aspx"/>后,访问首页就不出来了,要加上/in ...

  6. auto_ash

    #!/usr/bin/ksh ##############paramter######################startdate=$1' 00:00:01'enddate=$2' 23:59: ...

  7. PHP导出Excel 数字末尾变0或小数点解决办法

    为了管理方便,查阅直观性.很多网站, 或者系统都会自带导出excel或者cvs的功能.但是很多情况下,由于数字超过15位,会被显示成0或者加小数点处理.造成这种情况是由于Excel内 置的数值有效范围 ...

  8. Notes over compiling..

    When compiling VIM on windows, using nmake may be a better choice.. Because so far my attempts to co ...

  9. myeclipse 2013 SR2 安装svn

    1.下载SVN-site-1.8.22.zip 2.找到MyEclipse安装路径 我的是F:\tool\myeclipse2013\dropins,复制SVN-site-1.8.22.zip到此文件 ...

  10. UVALive 2324 Human Gene Functions(动态规划)

    题意:求出将两个字符串改成一样长度所能形成最大的相似度. 思路:这个可以说是编辑距离的一个变形,编辑距离最终状态时要两个字符串完全一致,这个就是要求长度一样,而且这个只允许插入“—”这一个字符.模仿编 ...