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. 【POJ2482】【线段树】Stars in Your Window

    Description Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw ...

  2. 【BZOJ3673】【可持久化并查集】可持久化并查集 by zky

    Description n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n ...

  3. 【Ural1057】幂和的数量

    [题目描述] 写一个程序来计算区间[X,Y]内满足如下条件的整数个数:它恰好等于K个互不相等的B的整数幂之和. 举个例子.令X=15,Y=20,K=2,B=2.在这个例子中,区间[15,20]内有3个 ...

  4. Android开发系列----学习伊始

    因为对移动端开发开始感兴趣,开始学习App开发,没有苹果环境的我,只好先选择Android来玩一玩了~~ 找了一套视频,买了几本java.android开发的书,开始搞起~~

  5. linux下gdal的python包的安装

    由于python包是从C++包编译出来的,所以需要先下载源码进行编译安装.1. gdal下载http://download.osgeo.org/gdal/CURRENT/sudo ./configur ...

  6. 在Adobe Reader中保存PDF表单数据的方法

    通常,Adobe Reader 用户填写表单后,是无法保存所填表单的副本的.但是,对于 Reader 8 和更高版本的用户,您可以扩展其权限,使他们可以完成此操作.如果您使用的是 Acrobat Pr ...

  7. 使用C语言获取当前系统的时间

    要想使用C语言来获取当前系统的时间,办法如下: 需要提前准备的工作: #include <stdio.h> #include <time.h> #include <std ...

  8. 使用ToUpperInvariant避免使用ToUpper

    ToUpperInvariant使用不依赖于区域性进行转换,而ToUpper则使用了当前线程的CultureInfo,进行转换,所以性能会有所影响,以下为测试: [Test] public void ...

  9. php开发入门教程

    LAMP window:WAMP(windows,apache,mysql,php) LAMP是 Linux,Apache,MySQL和PHP的缩写,是我们提供 Web 服务的软件基础. 对于 Lin ...

  10. 6.ListView

    Repeater一般只用来展示数据,如果要增删改则用ListView更方便,使用向导(强类型数据)来使用ListView会自动生成很多模板,免去手写模板代码的麻烦,再进行手工调整即可. 首先设定数据源 ...