关闭

Java4Android第10课_1:JNI--java调用

104人阅读 评论(0) 收藏 举报
分类:

Java Native Interface (JNI)是本地编程接口,它使得在 Java 虚拟机内部运行的 Java 代码能够与用其它编程语言(如 C、C++ 和汇编语言)编写的应用程序和库进行交互操作。

Native Method:使用关键字native修饰,表示该方法的实现由非java语言实现(比如C),
下面给了一个示例:    
    public class INatives
    {
      native public void Native1(String str) ;
      native static public int Native2() ;
    } 

使用本地代码的情形:
1、在该种语言中,已经有了大量测试过的和调试过的代码,且功能成熟稳定,这时候,若将这些代码移植到java语言就会显得很费时。
2、java代码通常占内存比较大,有时会降低系统性能,而像 C/C++ 它们的运行效率会高的多,当代码的执行速度至关重要的时候,可以考虑使用本地代码。
3、如果当前应用程序需要访问系统的各个特性和设备时。


Java调用c库函数的步骤:

1、java程序中使用System.loadLibrary加载c库,会导致c库中的jint JNI_OnLoad(JavaVM *jvm, void *reserved)被调用

2、在c库里面,建立java方法与c函数的映射

3、java程序中调用c库的函数

例子:

JNIDemo.java:

public class JNIDemo{
/*1. load c library*/
static{
System.loadLibrary("native");
}
public native int hello(int m);
public static void main(String args[]){
JNIDemo d = new JNIDemo();
/*3. call*/
System.out.println(d.hello(100));
}
}

native.c:

#include <jni.h>  /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */
#include <stdio.h>
#if 0
typedef struct {
    char *name;          /* Java里调用的函数名 */
    char *signature;    /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */
    void *fnPtr;          /* C语言实现的本地函数 */
} JNINativeMethod;
#endif

jint c_hello(JNIEnv *env, jobject cls, jint m)
{
printf("Hello, world! val = %d\n", m);
return m+1;
}

static const JNINativeMethod methods[] = {
{"hello", "(I)I", (void *)c_hello},
};

/* System.loadLibrary */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv *env;
jclass cls;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
return JNI_ERR; /* JNI version not supported */
}
cls = (*env)->FindClass(env, "JNIDemo");
if (cls == NULL) {
return JNI_ERR;
}

/* 2. map java hello <-->c c_hello */
if ((*env)->RegisterNatives(env, cls, methods, 1) < 0)
return JNI_ERR;

return JNI_VERSION_1_4;
}

在linux下的编译方法:
javac JNIDemo.java
javah -jni JNIDemo //得到一个JNIDemo.h,里面有本地方法的定义格式和字段描述符
gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.so native.c
export LD_LIBRARY_PATH=.
java JNIDemo


java和c库之间传递数据:

1、基本数据类型,直接使用、直接返回

2、传递字符串:

以下函数从Java中获得一个字符串,
再返回一个字符串给Java:


JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const jbyte *str;
str = (*env)->GetStringUTFChars(env, prompt, NULL);
if (str == NULL) {
return NULL; /* OutOfMemoryError already thrown */
}
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
/* We assume here that the user does not type more than 127 characters */
scanf("%s", buf);
return (*env)->NewStringUTF(env, buf);
}

3、传递数组

以下函数从Java中获得一个int数组,
再求和返回一个整数给Java:

JNIEXPORT jint JNICALL
Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint *carr;
jint i, sum = 0;
carr = (*env)->GetIntArrayElements(env, arr, NULL);
if (carr == NULL) {
return 0; /* exception occurred */
}
for (i=0; i< (*env)->GetArrayLength(env, arr); i++) {
sum += carr[i];
}
(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
return sum;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:22222次
    • 积分:385
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:77篇
    • 译文:0篇
    • 评论:0条