我们下面就看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):