JNI学习一(入门篇)

来源:互联网 发布:facebook好友推荐算法 编辑:程序博客网 时间:2024/05/16 10:45

JNI之特性

JNI特性:

1、  native code 底层操作,更加高效

2、  打破了java的平台无关性,可移植性需要自己解决

3、  Java面向对象语言的封装性被破坏了,Java类中任何方法和属性对JNI都是可见的,包括private

4、  从java环境到native code的上下文切换耗时、低效

5、  JNI编程,操作不当,可能引起内存泄露

 

JNI之quick start

JNI入门最大的问题是,如何将Java层的声明为native的函数和JNI层的函数联系起来,下面介绍两种方法

一、使用javah生成JNI层函数的函数名

1、  创建一个类(HelloWorld.java)

class HelloWorld {

           privatenative void print(); // 申明native方法

           publicstatic void main(String[] args) {

                    newHelloWorld().print();

           }

 

           static {

                    System.loadLibrary(“HelloWorld”);

           }

}

2、  使用javac编译该类,生成HelloWorld.class

$javac HelloWorld.java

3、  利用javah –jni产生头文件。“-jni”为默认参数,可以不写

$javah –jni HelloWorld

这行命令会生成HelloWorld.h文件,里面会有前面native函数的声明

JNIEXPORT void JNICALL

Java_HelloWorld_print(JNIEnv *, jobject);

4、  用本地代码实现头文件中定义的方法

新建HellocWorld.c文件,写入如下内容:

#include <jni.h>

#include <stdio.h>

#include “HelloWorld.h”

 

JNIEXPORT void JNICALL

Java_HelloWorld_print(JNIEnv *env, jobject obj) {

           printf(“HelloWorld!\n”);

           return;

}

 

5、  Run

5.1 生成动态库

Linux 下编译生成动态库:gcc HellocWorld.c –fPIC –shared –o libHelloWorld.so

Windows下编译生成动态库: cl –I c:\java\include –I c:\java\include\win32 –MD –LD HelloWorld.c–Fe HelloWorld.dll

 

5.2配置编译环境,保证能够找到我们生成的动态库

java –D java.library.path=.HelloWorld

 

5.3 Run the program

$java HelloWorld

输出:Hello World!

二、在android中,非常多的使用了动态注册函数名

直接示例:MediaPlayer中的native函数

1、  MediaPlayer.java

 

static {

        System.loadLibrary("media_jni");

        native_init();

}

private static native final void native_init();

 

2、  android_media_MediaPlayer.cpp

当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找该库中是否有JNI_OnLoad函数,如果有就调用它,动态注册的工作就是在这里完成。

 

jint JNI_OnLoad(JavaVM* vm, void* reserved) {

        JNIEnv* env = NULL;

        jintresult = -1;

 

        if(vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

                ALOGE("ERROR: GetEnv failed\n");

                goto bail;

        }

        assert(env != NULL);

 

        // 完成MediaPlayer用到的Native函数的动态注册

        if(register_android_media_MediaPlayer(env) < 0) {

                ALOGE("ERROR: MediaPlayer nativeregistration failed\n");

                goto bail;

        }

 

        /*success -- return valid version number */

        result =JNI_VERSION_1_4;

 

        bail:

               return result;

}

 

static int register_android_media_MediaPlayer(JNIEnv*env) {

         return AndroidRuntime::registerNativeMethods(env,

         "android/media/MediaPlayer", gMethods,NELEM(gMethods));

}

 

static JNINativeMethod gMethods[] = {

           // 通过这里映射,当Java层调用native_init方法时,

          android_media_MediaPlayer_native_init就会被执行

          {"native_init", "()V",(void *)android_media_MediaPlayer_native_init},

          // some other native method

}
1 0
原创粉丝点击