1:JNI是什么?

Java NativeInterface(JNI)是Java提供的一个很重要的特性。它使得用诸如C/C++等语言编写的代码可以与运行于Java虚拟机(JVM)中的 Java代码集成。有些时候,Java并不能满足你的全部开发需求,比如你希望提高某些关键模块的效率,或者你必须使用某个以C/C++等Native语 言编写的程序库;此时,JNI就能满足你在Java代码中访问这些Native模块的需求。JNI的出现使得开发者既可以利用Java语言跨平台、类库丰 富、开发便捷等特点,又可以利用Native语言的高效。

2:JNI和JVM什么关系?

JNI是JVM实现中的一部分,因此Native语言和Java代码都运行在JVM的宿主环境(Host Environment)。此外,JNI是一个双向的接口:开发者不仅可以通过JNI在Java代码中访问Native模块,还可以在 Native代码中嵌入一个JVM,并通过JNI访问运行于其中的Java模块。可见,JNI担任了一个桥梁的角色,它将JVM与Native模块联系起来,从而实现了Java代码与Native代码的互访。在OPhone上使用Java虚拟机是为嵌入式设备特别优化的Dalvik虚拟机。每启动一个应 用,系统会建立一个新的进程运行一个Dalvik虚拟机,因此各应用实际上是运行在各自的VM中的。Dalvik VM对JNI的规范支持的较全面,对于从JDK 1.2到JDK 1.6补充的增强功能也基本都能支持。

开发者在使用JNI之前需要充分了解其优缺点,以便合理选择技术方案实现目标。JNI的优点前面已经讲过,这里不再重复,其缺点也是显而易见的:由于Native模块的使用,Java代码会丧失其原有的跨平台性和类型安全等特性。此外,在JNI应用中,Java代码与Native代码运行于同一个进程空间内;对于跨进程甚至跨宿主环境的Java与Native间通信的需求,可以考虑采用socket、Web Service等IPC通信机制来实现。

3:JNI在JAVE和c++中互操作性;

a:java和c++的基本调用:

完整的例子:  http://www.2cto.com/kf/201203/123039.html

b:JNIhelper的概念和用法:

完整的例子:http://codingnow.cn/cocos2d-x/992.html,就是编译的时候,会出现编译的error,想调试的哥们,try一下;问题不大;

c:独立JNIhelper的使用:

http://blog.csdn.net/penguu8/article/details/9629627

4:JNI的编译

Android.mk的编译配置:

http://blog.csdn.net/penguu8/article/details/9667301

编译的基本命令:

http://blog.csdn.net/penguu8/article/details/9667333

5: JNI用法品读

(1).andorid CPP调用java函数和访问其成员:

原理 => CPP代码找到java的那个class里面的函数的入口地址,然后在CPP代码中调用java代码

步骤1) 用FindClass()函数找到该java类(如android.os.Binder)的实例对象的引用:

jclass clazz =env->FindClass(kBinderPathName) =env->FindClass("android.os.Binder")

步骤2) 用GetFieldID()函数获取到要访问的域(field: 实际上就是该java class中的某个成员变量的名字)的ID:

gBinderOffsets.mObject= env->GetFieldID(clazz, "mObject", "I") // mObject为java class "Binder"里的一个成员变量

-> 注意,这里将要访问的那个java对象的成员mObject的ID保存到了全局变量gBinderOffsets.mObject中,这样做的前提和优点如下:

前提: android里面,每个java进程中只允许有一个java虚拟机(sun公司原始的java架构中,一个进程中可以有多个java虚拟机)

优点: 除了第一次,以后每次要访问该java对象的成员mObject就非常快了(不用再去FindClass()和GetFieldID())

步骤3) 用GetMethodID()函数获取到要访问的方法(Method: 实际上就是该java class中的某个成员函数的名字)的ID:

gBinderOffsets.mExecTransact= env->GetMethodID(clazz, "execTransact", "(IIII)Z") //execTransact为java class "Binder"里的一个成员函数

步骤4) 用类似于GetIntField()的函数获取到该java对象的那个域(即成员)的值:

IBinder* target =(IBinder*)env->GetIntField(obj,gBinderProxyOffsets.mObject)

// 获取javaandroid.os.Binder类型对象里面的成员mObject的值

步骤5) 用类似于CallBooleanMethod()的函数调用到该java对象的那个成员函数:

jboolean res =env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code,(int32_t)&data, (int32_t)reply, flags)

(2).android java调用CPP函数:

原理 => 相当于java的那个class里面有的函数使用CPP代码来实现了

1)通过结构JNINativeMethod描述java代码调用函数和CPP函数的对应关系:

typedef struct {

const char* name; //java代码调用CPP函数的入口

const char*signature; // CPP函数的返回值

void* fnPtr; // CPP的函数名

} JNINativeMethod;

=> 例如: java代码通过IBinder.transact()来调用CPP的函数android_os_BinderProxy_transact()

{"transact","(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z",(void*)android_os_BinderProxy_transact},

2)将CPP函数注册到java的某个class中: 使用函数AndroidRuntime::registerNativeMethods()来注册

=> 这之后,java代码就可以调用CPP函数了

3)java代码调用CPP函数方法:

IBinder.transact()

总结其原理:C/C++要调用JAVA程序,必须先加载JAVA虚拟机,由JAVA虚拟机解释执行class文件。为了初始化JAVA虚拟机,JNI提供了一系列的接口函数,通过这些函数方便地加载虚拟机到内存中。


[置顶] Android JNI必须掌握的五点的更多相关文章

  1. [置顶] Android开发笔记(成长轨迹)

    分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...

  2. [置顶] Android Sensor系统剖析(4.0)(下)

    Author:Harish_hu@qq.com 由于现在电脑上只有4.0的代码,考虑到代码差别也不大,所以下部分,就基于4.0来分析.  3:SensorManager 上一部分说过,开机后,syst ...

  3. [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so

    0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...

  4. [置顶] android利用jni调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so

    0:前言 1:本文主要作为丙方android公司的身份来写 2:作者有不对的地方,请指出,谢谢 [第一篇:android利用jni调用第三方库——编写库libhello.so] [第二篇:androi ...

  5. [置顶] [Android源码分析]inquiry result引起的上层变化分析

    在上一篇文章中,我们详细分析了android是如何解析蓝牙反馈上来的搜索到的设备信息,本文将会继续分析这些信息到了上层之后是如何处理. 8.inquiry result引起的上层变化 我们知道inqu ...

  6. [置顶] Android AlarmManager实现不间断轮询服务

    在消息的获取上是选择轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了.但如果只是一般的消息检测比如更新检查,可能是半个小时或一个小时一 ...

  7. [置顶] Android安全机制分析

    Android系统是基于Linux内核开发的,因此,Android系统不仅保留和继承了Linux操作系统的安全机制,而且其系统架构的各个层次都有独特的安全特性[2] . 1. Linux内核层安全机制 ...

  8. [置顶] Android四大组件之BroadcastReceiver

    Android四大组件之BroadcastReceiver Broadcast Receiver 广播接收器,是一种负责接收广播消息并对消息做出响应的组件,和Service一样并不提供与用户交互的UI ...

  9. [置顶] android系统如何在静音模式下关闭camera拍照声音(2)

    之前写过一篇“android系统如何在静音模式下关闭camera拍照声音”的博客,今天来写他的续篇,继续探讨这个问题. 公司新需求,要求在camera应用中添加一个开关,可以进行拍照声音的关闭和开启. ...

随机推荐

  1. 使用require.js时,解决AMD封装jquery1.4.1的问题。

    require.config({ baseUrl: "js/", paths: { "jquery": "jquery-1.4.1.min" ...

  2. 虚拟机VHD格式解析到NTFS文件系统解析

    本来的需求是XEN下的镜像取证,但这篇仅包括他支持的一种格式,就是VHD,此项目从头开始大概用了两周时间,中间遇到了很多让人头大的问题,光是思考的笔记就写了十几页纸,不过实际上并没有那么难,主要是很久 ...

  3. 关于css float 属性以及position:absolute 的区别。

    1.float 属性定义元素在哪个方向浮动.以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动.浮动元素会生成一个块级框,而不论它本身是何种元素.div一个典型的块 ...

  4. C# 控制台程序设置字体颜色

    这几天做了个程序,程序本身很简单.大体功能是输入查询条件,从数据库里取出结果计算并显示.但是用户的要求是使用控制台(console)来实现功能.由于功能简单,程序很快就做完了,在面向用户演示程序时,突 ...

  5. css学习--inline-block详解及dispaly:inline inline-block block 三者区别精要概括

    *知识储备: 内联元素:是不可以控制宽和高.margin等:并且在同一行显示,不换行. 块级元素:是可以控制宽和高.margin等,并且会换行. 1.inline-block 详解 (1)一句话就是在 ...

  6. QTP的DataTable操作整理(注---不知转载多少遍)

    返回值:数字 示例: 以下示例使用 GetRowCount 方法查找 MySheet 运行时数据表中最长的列中的总行数,并将其写入报告. rowcount = DataTable.GetSheet(& ...

  7. dede定义全局变量(include/common.inc.php)及调用方式

    dede定义全局变量的文件include/common.inc.php及使用   在include/common.inc.php文件里,dede定义了大量的全局变量,详细自己去看看   dede模板里 ...

  8. DEDECMS 关键字不能小于2个字节!

    今天在做DEDECMS模板时,突然遇到了“关键字不能小于2个字节!”晕,是怎么回事呢?百度了一下,找到了答案,把他记录下来,方便自己日后再遇到这种问题时,可以查询: <form name=&qu ...

  9. python模块之hashlib加密

    40.加密模块:hashlib      1.           >>> import hashlib >>> ret1 = hashlib.md5()     ...

  10. C++实现base64编码

    将昨天的php代码改造成C++ /*base_64.h文件*/ #ifndef BASE_64_H #define BASE_64_H /** * Base64 编码/解码 * @author lir ...