Java JNI的使用基础(2)


我们下面就看JNI部分。我们这里可以再建立一个JNI的工程,方便后面使用shell进行编译。首先,在此工程里创建一个C源文件,文件名可以随便命名,.c作为后缀即可,这里用a.c:

#include <jni.h>

extern int __attribute__((fastcall)) asmTest(void);

JNIEXPORT jint JNICALL Java_test_Main_myJNITest(JNIEnv *env, jobject obj)
{
    return 100 + asmTest();   
}

这里的asmTest函数就定义在一个汇编文件里,下面将会看到。这里使用fastcall调用规则,使得参数以及返回值都能在寄存器中,这样可以方便汇编函数对实参的获取。当然,在64位应用环境下就不需要fastcall了。因为64位环境下,x86-64遵循的是System-V的函数调用约定,具体可参考——?tid-66986.html

下面看看汇编源文件(asmtest.s):

.text
.align 2

.globl asmTest

asmTest:

mov        $15, %eax
    ret

完成了C源代码以及汇编代码之后,我们将写一个简单的shell文件把它们分别编译,然后再连接成一个so动态共享库文件。

gcc -Wall -c -I/home/zenny_chen/MyPrograms/eclipse/jdk/include -I/home/zenny_chen/MyPrograms/eclipse/jdk/include/linux a.c
gcc -Wall -c asmtest.s
gcc -shared -z noexecstack -o libctest.so a.o asmtest.o

由于jni.h在 jdk/include 下,而jni_md.h则是在 jdk/include/linux 下(其它操作系统则是其它操作系统的名称),因此,这里要把两个头文件包含路径都加上。另外,最后的-z noexecstack要加,因为Java会对栈进行检查,如果没有此连接选项,Java在调用此函数时就会报warning(比较烦人,呼呼~)。最后,连接生成的库名就是libctest.so,这个文件名必须与Java中loadLibrary的库名一致。

Oracle官方对JNI的说明文档(基于Java8):

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/53f1a3c0ded17cd6422fa8ed76f7733d.html