Linux下JNI的调用

来源:互联网 发布:世界各国软件行业排名 编辑:程序博客网 时间:2024/06/07 06:23

   凡事想要占得头筹,准备工作总要占得先机。羊总是要入口的,至于入虎口还是入狮口就要看各自的实力。在以结果为导向的普世价值之下,羊是顺过来还是买过来区别并不是很大。“顺手牵羊”这一招已经成为弥补自身不足之利器被广泛运用,从操作系统的羊(当然,我觉得这已经不是牵来一只羊,而是引进一名外国厨子),到微信的羊,再到百度的羊,不同的只是你希望吃涮羊肉呢,还是喜欢听“咩咩”的叫声。

   在我看来,c++就是这样一只羊。虽然Java与c++之争源来已久,但并不妨碍Java在很多底层领域无奈的叹息——她已经太久没有尝过羔羊鲜嫩的膻味了。于是自创一套顺手牵羊的绝技——JNI,来进行猎羊行动。狩猎是保护生态的行为吗,是吗,不是吗?

    通过JNI可以java调用cc++中的方法。简单说一下Linux下的调用方式。

1 新建java类

    首先新建一个java类:

    com.JniFile.java

    内容如下:

    package com;    public class JniFile {        public native void jniHelloWorld();        static {                System.loadLibrary("jnitest");        }        public static void main(String[] args) {                new JniFile().jniHelloWorld();        }    }

注意此处“jnitest”是未来要加载的包名。


编译java类

    对其进行编译:

    javac ./com/JniFile.java

会在com目录下生成相应的class文件:

    [root@localhost jnitest]# ll ./com/    total 8    -rw-r--r--. 1 root root 458 Sep  4 16:09 JniFile.class    -rw-r--r--. 1 root root 265 Sep  4 15:55 JniFile.java

生成.h头文件

    然后要使用javah命令生成头文件:

    [root@localhost jnitest]# javah -jni com.JniFile

查看一下:

    [root@localhost jnitest]# ll    total 8    drwxr-xr-x. 2 root root 4096 Sep  4 16:09 com    -rw-r--r--. 1 root root  398 Sep  4 16:11 com_JniFile.h

查看头文件的内容:

    [root@localhost jnitest]# vi com_JniFile.h    /* DO NOT EDIT THIS FILE - it is machine generated */    #include <jni.h>    /* Header for class com_JniFile */    #ifndef _Included_com_JniFile    #define _Included_com_JniFile    #ifdef __cplusplus    extern "C" {    #endif    /*     * Class:     com_JniFile     * Method:    jniHelloWorld     * Signature: ()V     */    JNIEXPORT void JNICALL Java_com_JniFile_jniHelloWorld      (JNIEnv *, jobject);    #ifdef __cplusplus    }    #endif    #endif

注意该头文件中的方法:

    JNIEXPORT void JNICALL Java_com_JniFile_jniHelloWorld      (JNIEnv *, jobject)

    需要在相应的cpp文件中实现。

接下来新建一个cpp文件:

[root@localhost jnitest]# vi ./JniFileImpl.cpp


创建cpp文件

接下来新建一个cpp文件:

    [root@localhost jnitest]# vi ./JniFileImpl.cpp
        内容如下:

    #include <jni.h>    #include <stdio.h>    #include "com_CheckFile.h"    JNIEXPORT void JNICALL Java_com_JniFile_jniHelloWorld      (JNIEnv *, jobject)    {        printf("JNI cpp file: JniFileImpl.cpp\n");        printf("JNI cpp method: Java_com_JniFile_jniHelloWorld\n");        printf("Hello world ! \n");        return;    }

注意这个时候当前目录有文件:

    [root@localhost jnitest]# ll    total 12    drwxr-xr-x. 2 root root 4096 Sep  4 16:09 com    -rw-r--r--. 1 root root  398 Sep  4 16:11 com_JniFile.h    -rw-r--r--. 1 root root  297 Sep  4 16:22 JniFileImpl.cpp

而其中的com文件夹下有文件:

    [root@localhost jnitest]# ll com/    total 8    -rw-r--r--. 1 root root 458 Sep  4 16:09 JniFile.class    -rw-r--r--. 1 root root 265 Sep  4 15:55 JniFile.java


生成动态链接库

    接下来利用g++命令生成Linux下的动态链接库so文件:

    [root@localhost jnitest]# g++ -shared -I /opt/java/jdk1.7.0_67/include/ -I /opt/java/jdk1.7.0_67/include/linux -fPIC JniFileImpl.cpp -o libjnitest.so

    可以看到当前目录下多了一个libjnitest.so文件:

    [root@localhost jnitest]# ll    total 20    drwxr-xr-x. 2 root root 4096 Sep  4 16:09 com    -rw-r--r--. 1 root root  398 Sep  4 16:11 com_JniFile.h    -rw-r--r--. 1 root root  297 Sep  4 16:22 JniFileImpl.cpp    -rwxr-xr-x. 1 root root 6499 Sep  4 16:25 libjnitest.so

运行

    运行现在我们就可以执行刚才生成的java类文件来查看运行效果了: 

    [root@localhost jnitest]# java -Djava.library.path=. com.JniFile    JNI cpp file: JniFileImpl.cpp    JNI cpp method: Java_com_JniFile_jniHelloWorld    Hello world ! 

    注意要带着“java.library.path”这个参数,它指定了动态链接库的位置。可以在SystemgetProperties方法中获得此参数的含义。

    在windows下实践JNI调用也可以得到同样的效果。













0 0
原创粉丝点击