科技: 人物 企业 技术 IT业 TMT
科普: 自然 科学 科幻 宇宙 科学家
通信: 历史 技术 手机 词典 3G馆
索引: 分类 推荐 专题 热点 排行榜
互联网: 广告 营销 政务 游戏 google
新媒体: 社交 博客 学者 人物 传播学
新思想: 网站 新书 新知 新词 思想家
图书馆: 文化 商业 管理 经济 期刊
网络文化: 社会 红人 黑客 治理 亚文化
创业百科: VC 词典 指南 案例 创业史
前沿科技: 清洁 绿色 纳米 生物 环保
知识产权: 盗版 共享 学人 法规 著作
用户名: 密码: 注册 忘记密码?
    创建新词条
科技百科
  • 人气指数: 2923 次
  • 编辑次数: 1 次 历史版本
  • 更新时间: 2009-03-11
admin
admin
发短消息
相关词条
SIM卡
SIM卡
WEBSPHERE
WEBSPHERE
FTP
FTP
並行計算
並行計算
国外计算机科学状况
国外计算机科学状况
混龄教育
混龄教育
学科信息门户
学科信息门户
UBUNTU
UBUNTU
恩尼格玛
恩尼格玛
广播工程师
广播工程师
推荐词条
希拉里二度竞选
希拉里二度竞选
《互联网百科系列》
《互联网百科系列》
《黑客百科》
《黑客百科》
《网络舆情百科》
《网络舆情百科》
《网络治理百科》
《网络治理百科》
《硅谷百科》
《硅谷百科》
2017年特斯拉
2017年特斯拉
MIT黑客全纪录
MIT黑客全纪录
桑达尔·皮查伊
桑达尔·皮查伊
阿里双十一成交额
阿里双十一成交额
最新词条

热门标签

微博侠 数字营销2011年度总结 政务微博元年 2011微博十大事件 美国十大创业孵化器 盘点美国导师型创业孵化器 盘点导师型创业孵化器 TechStars 智能电视大战前夜 竞争型国企 公益型国企 2011央视经济年度人物 Rhianna Pratchett 莱恩娜·普莱契 Zynga与Facebook关系 Zynga盈利危机 2010年手机社交游戏行业分析报告 游戏奖励 主流手机游戏公司运营表现 主流手机游戏公司运营对比数据 创建游戏原型 正反馈现象 易用性设计增强游戏体验 易用性设计 《The Sims Social》社交亮 心理生理学与游戏 Kixeye Storm8 Storm8公司 女性玩家营销策略 休闲游戏的创新性 游戏运营的数据分析 社交游戏分析学常见术语 游戏运营数据解析 iPad风行美国校园 iPad终结传统教科书 游戏平衡性 成长类型及情感元素 鸿蒙国际 云骗钱 2011年政务微博报告 《2011年政务微博报告》 方正产业图谱 方正改制考 通信企业属公益型国企 善用玩家作弊行为 手机游戏传播 每用户平均收入 ARPU值 ARPU 游戏授权三面观 游戏设计所运用的化学原理 iOS应用人性化界面设计原则 硬核游戏 硬核社交游戏 生物测量法研究玩家 全球移动用户 用户研究三部曲 Tagged转型故事 Tagged Instagram火爆的3大原因 全球第四大社交网络Badoo Badoo 2011年最迅猛的20大创业公司 病毒式传播功能支持的游戏设计 病毒式传播功能 美国社交游戏虚拟商品收益 Flipboard改变阅读 盘点10大最难iPhone游戏 移动应用设计7大主流趋势 成功的设计文件十个要点 游戏设计文件 应用内置付费功能 内置付费功能 IAP功能 IAP IAP模式 游戏易用性测试 生理心理游戏评估 游戏化游戏 全美社交游戏规模 美国社交游戏市场 全球平板电脑出货量 Facebook虚拟商品收益 Facebook全球广告营收 Facebook广告营收 失败游戏设计的数宗罪名 休闲游戏设计要点 玩游戏可提高认知能力 玩游戏与认知能力 全球游戏广告 独立开发者提高工作效率的100个要点 Facebook亚洲用户 免费游戏的10种创收模式 人类大脑可下载 2012年最值得期待的20位硅谷企业家 做空中概股的幕后黑手 做空中概股幕后黑手 苹果2013营收 Playfish社交游戏架构

JNI
JNI
JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是CC++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java虚拟机实现下。

目录

[显示全部]

书写步骤编辑本段回目录

JNI
JNI
编写带有native声明的方法的java类
使用javac命令编译所编写的java类
使用javahjnijava类名生成扩展名为h的头文件
使用C/C++实现本地方法
将C/C++编写的文件生成动态连接库

1、编写java程序:这里以Hello World为例。

代码1:
classHelloWorld{
publicnativevoiddisplayHelloWorld();
static{
System.loadLibrary("hello");
}
publicstaticvoidmain(String[]args){
newHelloWorld().displayHelloWorld();
}
}
声明native方法:将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。Load动态库:System.loadLibrary("hello");加载动态库(可以这样理解:的方法displayHelloWorld()没有实现,但是在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。

2、编译

javacHelloWorld.java

3、生成扩展名为h的头文件javah

jniHelloWorld头文件的内容:/*DONOTEDITTHISFILE-itismachinegenerated*/
1.include
/*HeaderforclassHelloWorld*/
1.ifndef_Included_HelloWorld
2.define_Included_HelloWorld
3.ifdef__cplusplus
extern"C"{
1.endif
/*
*Class:HelloWorld
*Method:displayHelloWorld
*Signature:()V
*/
JNIEXPORTvoidJNICALLJava_HelloWorld_displayHelloWorld(JNIEnv*,jobject);
1.ifdef__cplusplus
}
1.endif
2.endif
(这个h文件相当于在java里面的接口,这里声明了一个Java_HelloWorld_displayHelloWorld(JNIEnv*,jobject);方法,然后在的本地方法里面实现这个方法,也就是说在编写C/C++程序的时候所使用的方法名必须和这里的一致)。

JNI
JNI
4、编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。

代码2:
1#include
2#include"HelloWorld.h"
3#include
4JNIEXPORTvoidJNICALLJava_HelloWorld_displayHelloWorld(JNIEnv*env,jobjectobj){printf("Helloworld!n");return;}
注意代码2中的第1行,需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入(相当于在编写java程序的时候,实现一个接口的话需要声明才可以,这里就是将HelloWorld.h头文件里面声明的方法加以实现。当然不一定是这样)。然后保存为HelloWorldImpl.c就好了。

5、生成动态库

这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c文件夹下面,使用VC的编译器cl成。cl-I%java_home%include-I%java_home%includewin32-LDHelloWorldImp.c-Fehello.dll注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%include-I%java_home%includewin32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。

6、运行程序javaHelloWorld。

使用实例编辑本段回目录

JNI
JNI
一个简单的例子实现打印一句话的功能,但是用的c的printf最终实现。一般提供给java的jni接口包括一个so文件(封装了c函数的实现)和一个java文件(需要调用path的类)。

1、JNI的目的是使java方法中能够调用c实现的一些函数,比如以下的java类,就需要调用一个本地函数testjni(一般声明为privatenative类型),首先需要创建文件weiqiong.java,内容如下:
classweiqiong{static{System.loadLibrary("testjni");//载入静态库,test函数在其中实现}privatenativevoidtestjni();//声明本地调用publicvoidtest(){testjni();}publicstaticvoidmain(Stringargs[]){weiqionghaha=newweiqiong();haha.test();}}

2、然后执行javacweiqiong.java,如果没有报错,会生成一个weiqiong.class。

3、然后执行javahweiqiong,会生成一个文件weiqiong.h文件,其中有一个函数的声明如下:
JNIEXPORTvoidJNICALLJava_weiqiong_testjni(JNIEnv*,jobject);

4、创建文件testjni.c将上面那个函数实现,内容如下:
1.include
2.include
JNIEXPORTvoidJNICALLJava_weiqiong_testjni(JNIEnv*env,jobjectobj){printf("haha---------gointoc!!!n");}

5、为了生成.so文件,创建makefile文件如下:
libtestjni.so:testjni.omakefilegcc-Wall-rdynamic-shared-olibtestjni.sotestjni.otestjni.o:testjni.cweiqiong.hgcc-Wall-ctestjni.c-I./-I/usr/java/j2sdk1.4.0/include-I/usr/java/j2sdk1.4.0/include/linuxcl:rm-rf*.o*.so注意:gcc前面是tab空,j2sdk的目录根据自己装的j2sdk的具体版本来写,生成的so文件的名字必须是loadLibrary的参数名前加“lib”。

6、exportLD_LIBRARY_PATH=.,由此设置library路径为当前目录,这样java文件才能找到so文件。一般的做法是将so文件copy到本机的LD_LIBRARY_PATH目录下。

7、执行javaweiqiong,打印出结果:“haha---------gointoc!!!”

程序调用编辑本段回目录

JNI
JNI
在首次使用JNI的时候有些疑问,后来在使用中一一解决,下面就是这些问题的备忘:

1、java和c是如何互通的。

其实不能互通的原因主要是数据类型的问题,jni解决了这个问题,例如那个c文件中的jstring数据类型就是java传入的String对象,经过jni函数的转化就能成为c的char*。

对应数据类型关系如下表:

Java类型本地c类型说明booleanjboolean无符号,8位bytejbyte无符号,8位charjchar无符号,16位shortjshort有符号,16位intjint有符号,32位longjlong有符号,64位floatjfloat32位doublejdouble64位voidvoidN/A。

2、如何将java传入的String参数转换为c的char*,然后使用。

java传入的String参数,在c文件中被jni转换为jstring的数据类型,在c文件中声明char*test,然后test=(char*)(*env)->;GetStringUTFChars(env,jstring,NULL);注意:test使用完后,通知虚拟机平台相关代码无需再访问:(*env)->;ReleaseStringUTFChars(env,jstring,test);

3、将c中获取的一个char*的buffer传递给java。

这个char*如果是一般的字符串的话,作为string传回去就可以了。如果是含有’’的buffer,最好作为bytearray传出,因为可以制定copy的length,如果copy到string,可能到’’就截断了。

有两种方式传递得到的数据:

一种是在jni中直接new一个byte数组,然后调用函数(*env)->;SetByteArrayRegion(env,bytearray,0,len,buffer);将buffer的值copy到bytearray中,函数直接returnbytearray就可以了。

一种是return错误号,数据作为参数传出,但是java的基本数据类型是传值,对象是传递的引用,所以将这个需要传出的byte数组用某个类包一下,如下:

classRetObj{publicbyte[]bytearray;}这个对象作为函数的参数retobj传出,通过如下函数将retobj中的byte数组赋值便于传出。代码如下:jclasscls;jfieldIDfid;jbyteArraybytearray;bytearray=(*env)->;NewByteArray(env,len);(*env)->;SetByteArrayRegion(env,bytearray,0,len,buffer);cls=(*env)->;GetObjectClass(env,retobj);fid=(*env)->;GetFieldID(env,cls,"retbytes","[B"]);(*env)->;SetObjectField(env,retobj,fid,bytearray);

4、不知道占用多少空间的buffer,如何传递出去。

在jni的c文件中new出空间,传递出去。java的数据不初始化,指向传递出去的空间即可。

编写技术编辑本段回目录

JNI
JNI图1
JNI(JavaNativeInterface,Java本地化方法)。图l是JNI技术实现的一般步骤。

(1)编写Java类代码

其中,需要JNI实现的方法应当用native关键字声明。在该类中,用System.1oadLibrary()方法加载需要的动态链接库。关键代码如下:
//Compute.java
publicclassCompute{
publicnativedoublecomp(doubleparams);
static{
//调用动态链接库
System.loadLibrary(“mathlib”);

}

(2)编译成字节代码

在这个过程中,由于采用了native关键字声明,Java编译器会忽视没有代码体的JNI方法部分。

(3)生成相关JNI方法的头文件

这个过程的实现一般是通过利用jlavah-jni*class生成的,也可以手工生成该文件;但是由于Java虚拟机是根据一定的命名规范完成对JNI方法的调用,所以手工编写头文件需要特别小心。
上述文件产生的头文件部分代码如下:
//Compute.h

extern“C”{
JNIEXPORTjdoubleJNICALLJava_Compute_comp(JNI-Env*,jobject,jdoubleArray);

JNI函数名称分为三部分:首先是Java关键字,供Java虚拟机识别;然后是调用者类名称(全限定的类名,其中用下划线代替名称分隔符);最后是对应的方法名称,各段名称之间用下划线分割。

JNI函数的参数也由三部分组成:首先是JNIEnv*,是一个指向JNI运行环境的指针;第二个参数随本地方法是静态还是非静态而有所不同一一非静态本地方法的第二个参数是对对象的引用,而静态本地方法的第二个参数是对其Java类的引用;其余的参数对应通常Java方法的参数,参数类型需要根据一定规则进行映射。

(4)编写相应方法的实现代码

在编码过程中,需要注意变量的长度问题,例如Java的整型变量长度为32位,而C语言为16位,所以要仔细核对变量类型映射表,防止在传值过程中出现问题。

(5)将JNI实现代码编译成动态链接库

编译过程是利用C/C++编译器实现的,当要使用生成的动态链接库时,调用者类中需要显式调用该链接库。
经过上述处理,基本上完成了一个包含本地化方法的Java类的开发。

软件开发编辑本段回目录

JNI
JNI图2
基于JNI的嵌入式手机软件开发实例

下面通过一个实例来描述运用JNI技术在手机上操纵摄像头,捕捉视频并存储图片的过程。

(1)活动/状态图

图2为捕捉视频并存储图片的活动/状态图
根据图2的活动/状态,具体的对应步骤如下:
①发起该流程。
②发起流程后,建立文件用于存储图片。
③用指针获得分配的缓冲器,用于存储获得的帧。
④将指针压栈(序列化缓冲器)。由于手机的内存较小,为了防止内存泄漏,Symbian操作系统有一个Cleanupstack的要求,即在使用指针时,用PushL把指针压入栈中,使用完后再用Pop弹出栈.如果在中间调用导致崩溃的函数时果真出现了问题,那么Cleanupstack可以通过调用该指针的析构函数回收占用的空间。
⑤操纵摄像头,捕捉视频,并将图像流从摄像头端传到缓冲器。
⑥将摄像头内的图像流存入缓冲器内,并将缓冲器内的流转化为文件流,存为jpg格式的文件,将指向缓冲器的指针弹栈。
⑦在过程⑥中,如果使用完了序列化的缓冲器,则要重新序列化缓冲器,以备后面使用。
⑧当接收到停止视频捕捉的信号后,关闭文件。
⑨流程结束。

(2)运用JNI技术的视频捕捉

子功能捕捉视频的实现是由操纵摄像头、视频播放(解码器准备)以及建立摄像头和手机之间的连接会话三个活动组成的。其中操纵摄像头是通过调用底层设备的驱动来实现的,需要利用JNI来实现,完成的方法包括准备、建立、删除、销毁摄像头等。视频播放的一系列过程也是通过c++代码来实现的,除了准备、建立、删除、销毁解码器外,还有开始、暂停、停止解码等。建立摄像头和手机之间的连接类似建立客户端和服务器连接,视频流从摄像头传到手机界面是通过多媒体会话来完成的。多媒体会话的建立、关闭、摧毁以及会话建立后的发送、取消、读取数据等也是JNI的应用范畴。

相关词条编辑本段回目录

参考资料编辑本段回目录

→如果您认为本词条还有待完善,请 编辑词条

词条内容仅供参考,如果您需要解决具体问题
(尤其在法律、医学等领域),建议您咨询相关领域专业人士。
0

标签: JNI

收藏到: Favorites  

同义词: 暂无同义词

关于本词条的评论 (共0条)发表评论>>

对词条发表评论

评论长度最大为200个字符。