1、概述java
上一篇写的是经过javah工具将java代码中的native声明的函数生成标准的C/C++函数头,每一个函数的名字都很长(Java_包名_类名_函数名),这样C/C++函数的函数名就是定死的,不能修改,不然java找不到函数。这里还有种方式,经过注册的方式将C/C++的函数与java中的native函数进行一一对应的,函数名能够任意书写。linux
2、代码实现bash
SimpleJni.java函数
package com.bt.jni; public class SimpleJni { static { System.out.println("[java]static code block, start load shared library...."); System.loadLibrary("simpleJni"); System.out.println("[java]load library end...."); } static native int add(int a, int b); public static void main(String args[]) { System.out.println("[java] in main()..."); System.out.println("[java] 3 + 5 = " + SimpleJni.add(3, 5)); System.out.println("[java] main() end..."); } }
simple_jni.c工具
#include "jni.h" #include <stdio.h> const char *classPathName = "com/bt/jni/SimpleJni"; /** native 函数的实现 **/ jint myadd(JNIEnv *env, jobject thiz, jint a, jint b) { return a + b; } static JNINativeMethod methods[] = { //{native函数名,函数签名, C中函数实现名} {"add", "(II)I", (void*)myadd}, }; int registerNatives(JNIEnv *env) { jclass clazz; //根据类的全路径,得到类的字节码信息 clazz = (*env)->FindClass(env, classPathName); if (NULL == clazz) { printf("[C] FindClass() failed...\n"); goto failed; } //将c函数与字节码中的native函数进行映射 if (0 > (*env)->RegisterNatives(env, clazz, methods, sizeof(methods)/sizeof(methods[0]))) { printf("[C] RegisterNatives() failed...\n"); goto failed; } return JNI_TRUE; failed: return JNI_FALSE; } /** java 在加载动态库的时候,自动调用此函数,注册native函数 **/ jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env = NULL; jint result = -1; void **env_p = NULL; printf("[C] start register native func...\n"); env_p = (void**)&env; //首先从java虚拟机中得到env if (JNI_OK != (*vm)->GetEnv(vm, env_p, 0x00010004)) { printf("[C] GetEnv() failed...will exit\n"); goto err; } //经过env进行函数的注册 if (JNI_TRUE != registerNatives(env)) { printf("[C] register func failed...will exit\n"); goto err; } result = 0x00010004; printf("[C] register end...\n"); err: return result; }
操做步骤spa
1.首先编写SimpleJni.java和simpel_jni.c3d
2.编译java和c文件code
$ java -d . SimpleJni.java $gcc -fPIC -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -o libsimpleJni.so simple_jni.c
3.执行虚拟机
$java -Djava.library.path=. com.bt.jni.SimpleJni
结果:it
[java]static code block, start load shared library.... [C] start register native func... [C] register end... [java]load library end.... [java] in main()... [java] 3 + 5 = 8 [java] main() end...
根据结果可知,java首先执行静态代码块,其中在加载动态库的时候,自动调用JNI_OnLoad函数,创建native函数和c中的函数映射关系,最后进入main函数。