JNI靜態(tài)注冊和動態(tài)注冊區(qū)別

廢話不多說请琳,直接開始
Demo傳送門

注意:無論是動靜態(tài)注冊還是動態(tài)注冊,Java端代碼都是一樣的疙赠,所謂的靜動態(tài)注冊是指在C/C++里面的操作交掏,下面會具體講

靜態(tài)注冊

java代碼:

public class JniTest {
    static {
        System.loadLibrary("jniTest");
    }

    public static native String stringFromJNI();
    public static native String stringFromJniWithStr(Object context,String value);
}

C/C++代碼:

#include <jni.h>
#include <string>



extern "C" JNIEXPORT jstring JNICALL
Java_com_mirkowu_jintest_jni_JniTest_stringFromJNI(JNIEnv *env, jclass clazz) {
    std::string hello = "Hello from C++  by 靜態(tài)注冊";
    return env->NewStringUTF(hello.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_com_mirkowu_jintest_jni_JniTest_stringFromJniWithStr(JNIEnv *env, jclass clazz,
                                                          jobject context, jstring value) {

    const char *str = env->GetStringUTFChars(value, JNI_FALSE);
    return env->NewStringUTF(str);
}

動態(tài)注冊

動態(tài)注冊基本流程

  1. 編寫Java端的相關native方法
  2. 編寫C/C++代碼, 實現(xiàn)JNI_Onload()方法
  3. 將Java 方法和 C/C++方法通過簽名信息一一對應起來
  4. 通過JavaVM獲取JNIEnv, JNIEnv主要用于獲取Java類和調用一些JNI提供的方法
  5. 使用類名和對應起來的方法作為參數(shù), 調用JNI提供的函數(shù)RegisterNatives()注冊方法

所謂的動態(tài)注冊 是指,動態(tài)注冊JAVA的Native方法刨肃,使得c/c++里面方法名 可以和 java 的Native方法名可以不同古拴, 動態(tài)注冊是將將二者方法名關聯(lián)起來,以后在修改Native方法名時真友,只需修改動態(tài)注冊關聯(lián)的方法名稱即可黄痪。 System.loadLibrary("xxx"); 這個方法還是必須要調用的,不管動態(tài)還是靜態(tài)盔然。

java代碼:

public class JniDynamicRegisterTest {

    static {
        System.loadLibrary("dynamic_register");
    }

    public static native String a();
    public static native String b(Object context,String value);
}

C/C++代碼:

#include <jni.h>
#include <string>
#include <assert.h>

// ------------------------------- 以下是動態(tài)注冊 --------------------------------

jstring aaa(JNIEnv *env, jclass clazz) {
    std::string hello = "Hello from C++  by 動態(tài)注冊";
    return env->NewStringUTF(hello.c_str());
}

jstring getStringWithDynamicReg(JNIEnv *env, jclass clazz, jobject context, jstring value) {
    const char *str = env->GetStringUTFChars(value, JNI_FALSE);
    return env->NewStringUTF(str);
}



/**
 * 所謂的動態(tài)注冊 是指满力,動態(tài)注冊JAVA的Native方法,使得c/c++里面方法名 可以和 java 的Native方法名可以不同轻纪,
 * 動態(tài)注冊是將將二者方法名關聯(lián)起來油额,以后在修改Native方法名時,只需修改動態(tài)注冊關聯(lián)的方法名稱即可
 *  System.loadLibrary("xxx"); 這個方法還是必須要調用的刻帚,不管動態(tài)還是靜態(tài)
 */
#define JNIREG_CLASS "com/mirkowu/jintest/jni/JniDynamicRegisterTest"  //Java類的路徑:包名+類名
#define NUM_METHOES(x) ((int) (sizeof(x) / sizeof((x)[0]))) //獲取方法的數(shù)量


static JNINativeMethod method_table[] = {
        // 第一個參數(shù)a 是java native方法名潦嘶,
        // 第二個參數(shù) 是native方法參數(shù),括號里面是傳入?yún)⒌念愋停膺叺氖欠祷刂殿愋停?        // 第三個參數(shù) 是c/c++方法參數(shù),括號里面是返回值類型崇众,
        {"a", "()Ljava/lang/String;",                                     (jstring *) aaa},
        {"b", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;", (jstring *) getStringWithDynamicReg},

};

static int registerMethods(JNIEnv *env, const char *className,
                           JNINativeMethod *gMethods, int numMethods) {
    jclass clazz = env->FindClass(className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    //注冊native方法
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}


extern "C"
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {

    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    assert(env != NULL);

// 注冊native方法
    if (!registerMethods(env, JNIREG_CLASS, method_table, NUM_METHOES(method_table))) {
        return JNI_ERR;
    }

    return JNI_VERSION_1_6;
}

簽名

JNI 簽名
動態(tài)注冊中 JNINativeMethod 結構體中第二個參數(shù)需注意
括號內代表傳入?yún)?shù)的簽名符號掂僵,為空可以不寫航厚,括號外代表返回參數(shù)的簽名符號,為空填寫 V,對應關系入下表

簽名符號 C/C++ java
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
[Z jbooleanArray boolean[]
[I jintArray int[]
[J jlongArray long[]
[D jdoubleArray double[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
特殊的String
Ljava/lang/String; jstring String
L完整包名加類名; jobject class

舉個例子:
傳入的java參數(shù)有兩個 分別是 int 和 long[] 函數(shù)返回值為 String
即函數(shù)的定義為:String getString(int a ,long[] b)
簽名就應該是 :"(I[J)Ljava/lang/String;"(不要漏掉英文分號)
如果有內部類 則用 來分隔 如:Landroid/os/FileUtilsFileStatus;

總結

靜態(tài)注冊

  • 優(yōu)點: 理解和使用方式簡單, 屬于傻瓜式操作, 使用相關工具按流程操作就行, 出錯率低
  • 缺點: 當需要更改類名,包名或者方法時, 需要按照之前方法重新生成頭文件, 靈活性不高

動態(tài)注冊

  • 優(yōu)點: 靈活性高, 更改類名,包名或方法時, 只需對更改模塊進行少量修改, 效率高
  • 缺點: 對新手來說稍微有點難理解, 同時會由于搞錯簽名, 方法, 導致注冊失敗

參考

輸出多個so庫參考這里

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末锰蓬,一起剝皮案震驚了整個濱河市幔睬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芹扭,老刑警劉巖麻顶,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異舱卡,居然都是意外死亡辅肾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門轮锥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來矫钓,“玉大人,你說我怎么就攤上這事舍杜⌒履龋” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵既绩,是天一觀的道長杯活。 經(jīng)常有香客問我,道長熬词,這世上最難降的妖魔是什么旁钧? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮互拾,結果婚禮上歪今,老公的妹妹穿的比我還像新娘。我一直安慰自己颜矿,他們只是感情好寄猩,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骑疆,像睡著了一般田篇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上箍铭,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天泊柬,我揣著相機與錄音,去河邊找鬼诈火。 笑死兽赁,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播刀崖,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惊科,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了亮钦?” 一聲冷哼從身側響起馆截,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜂莉,沒想到半個月后蜡娶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡巡语,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年翎蹈,在試婚紗的時候發(fā)現(xiàn)自己被綠了淮菠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片男公。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖合陵,靈堂內的尸體忽然破棺而出枢赔,到底是詐尸還是另有隱情,我是刑警寧澤拥知,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布踏拜,位于F島的核電站,受9級特大地震影響低剔,放射性物質發(fā)生泄漏速梗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一襟齿、第九天 我趴在偏房一處隱蔽的房頂上張望姻锁。 院中可真熱鬧,春花似錦猜欺、人聲如沸位隶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涧黄。三九已至,卻和暖如春赋荆,著一層夾襖步出監(jiān)牢的瞬間笋妥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工窄潭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挽鞠,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像信认,于是被迫代替她去往敵國和親材义。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355