JNI入门——hello jni,jni入门hello
JNI入门——hello jni,jni入门hello
概念
JNI(Java Native Interface,Java本地接口),实现了Java和其他语言的交互(主要是C/C++)。使用java与本地已编译的其他代码交互,通常会丧失平台可移植性,应尽量避免,但在某些情况是有必要使用的,如为了使用一些旧的第三方库,与硬件、操作系统进行交互,或者为了提高程序的性能。
使用原因:
1. 功能:想直接使用C/C++编写好的功能,如与底层进行交互。
2. 效率:在一些复杂算法的处理上,使用C语言处理比起java高效很多
3. 安全:java是半解释型语言,很容易被反汇编后拿到源代码,因此可以在重要的交互功能使用C语言代替。
使用注意:
应该让native方法集中在少数几个类当中,以降低Java和其他语言之间的耦合。
入门使用
下面用JNI实现一个功能:Java代码将参数name传给C,C返回”hello,name”给Java进行输出。主要步骤是:
1.编写HelloJNI.java
代码如下,留意包名:
package com.kwws.demo.jni;
public class HelloJNI {
//用native关键字声明一个本地方法,将由C/C++进行实现
public native String getHello(String name);
//静态方法载入JNI_Hello库,不带后缀
static {
System.loadLibrary("JNI_Hello");
}
public static void main(String[] args) {
//JNI调用
String msg = new HelloJNI().getHello("jni");
System.out.println(msg);
}
}
2.编译HelloJNI.java
使用javac命令将.java编译为.class:
E:\JavaProject\HelloJNI\src\com\kwws\demo\jni>javac HelloJNI.java
当然,使用Eclipse编写的.java会自动编译,可以在以下路径找到.class:
\HelloJNI\bin\com\kwws\demo\jni\HelloJNI.class
3.生成JNI接口声明HelloJNI.h
使用javah命令将.java(.class?)中的本地方法抽象为接口,命名为.h。
定位到com.kwws.demo.jni.HelloJNI.java的上级目录\src,连同包名进行javah命令:
//定位到顶级包名所在目录;带完整包路径、不带.java后缀
E:\JavaProject\HelloJNI\src>javah com.kwws.demo.jni.HelloJNI
P.S.
实践中发现,javah命令好像对是.java代码进行的处理,不编译为.class也可得到.h文件。因此,步骤2可以跳过?
完成后,可在\src下看到生成的.h文件:
//com_kwws_demo_jni_HelloJNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_kwws_demo_jni_HelloJNI */
#ifndef _Included_com_kwws_demo_jni_HelloJNI
#define _Included_com_kwws_demo_jni_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_kwws_demo_jni_HelloJNI
* Method: getHello
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_kwws_demo_jni_HelloJNI_getHello
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
该文件中的方法Java_com_kwws_demo_jni_HelloJNI_getHello
就是.java中的对应方法在JNI中的调用接口,按“Java_包路径类名方法名”命名。
参数部分,第三个参数jstring对应Java中的唯一的string类型参数,而第1、2个参数是JNI交互使用的桥梁,应该是Java对象在内存中的指针。
4.用C/C++实现HelloJNI.h中的接口方法
编写C/C++,包含<jni.h>
(其中包含对JNIEnv、jobject等JNI对象的定义),以及自己的com_kwws_demo_jni_HelloJNI.h
(包含调用接口)。
其中对jstring参数的处理就省略掉了,直接返回新的字符串。
//JNI_Hello.c
#include <jni.h>
#include "com_kwws_demo_jni_HelloJNI.h"
JNIEXPORT jstring JNICALL
Java_com_kwws_demo_jni_HelloJNI_getHello
(JNIEnv *env, jobject obj, jstring name) { //需自行加上参数名
return (*env)->NewStringUTF(env, "hello from jni.");
}
P.S.
在C/C++中,对 JNIEnv *env 的使用方式不同:
// C: (*env)->
// C++: env->
5. 编译JNI_Hello.c为JNI_Hello.dll给Java调用
因为我好久没写C/C++的代码了,电脑上压根就没有C/C++的编译工具。主要是在Android学习中涉及了JNI的使用,而Android的NDK自带了C/C++的编译器。在Android的背景下,NDK编译生成.so文件供给Java层调用。
JNI独立使用时,编译C/C++代码成什么形式我不太确定(没特地去写),因此先留个问号,之后如果有遇到实践的机会再补充。
编译C/C++为动态链接库DLL,以及Java层的调用,可以参考:JNI的使用:HelloWorld
Eclipse集成JNI操作
前文中对JNI的操作都使用cmd命令,显然在工作中十分不便,好在可以将这些操作都集成到Eclipse中的按钮,一键完成任务。
参考:Eclipse集成JNI与AndroidNDK操作
参考
相关文章
- 暂无相关文章
用户点评