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函數。