JNI

What is JNI

JNI是Java Native Interface的縮寫,主要是提供了一系列API揣钦,讓你能在其它語言中寫Java。

What JNI can bring us

JNI最大的好處就是,額些阅,Java你懂的狐粱,跑在JVM里面舀寓,雖然有著一處編譯,到處運行的優(yōu)勢(肌蜻,方便盎ツ埂),但是它的效率蒋搜。篡撵。。至少相對于c和C艸來說豆挽,比較低下酸休,而且,正是由于這個能一處編譯祷杈,到處運行的原因斑司,Java極容易被反編譯。Java中一般用的加密方式就是混淆了,然而其實并沒有太大的作用宿刮。你還是開源吧互站。。僵缺。因為不開源也會被反編譯的胡桃。。磕潮。
PS:并沒有貶低Java的意思翠胰,個人還是挺喜歡用Java的

然后,相反的自脯,JNI由于是用C或者C艸寫之景,效率很高,可以用來處理一些底層的東西膏潮,比如解碼或者TCP/IP有關(guān)的锻狗。編譯過后跟C(艸)編譯的結(jié)果是一樣的,在Android里面是.so文件焕参。然后轻纪,因為是C(艸),所以需要針對不同的平臺叠纷,不同的處理器進行編譯刻帚。所以,使用JNI涩嚣,你需要在編譯的時候生成許多個平臺的版本崇众,否則,Java跨平臺這個優(yōu)點相當(dāng)于直接被廢了缓艳。還有就是JNI的調(diào)試會非常蛋疼。

How to use JNI

Hello World

我用的Android Studio看峻,有各種一鍵生成(x)阶淘,要看手擼的話,網(wǎng)上應(yīng)該能搜到互妓,本文主要是介紹那些遇到的坑溪窒。

AS生成的main.cpp長這樣:

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

extern "C"
jstring
Java_com_helloworld_jnidemo_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

分析一下:

  • 幾個include,其中jni.h是JNI必需的冯勉,其他的可以添加C(艸)中的澈蚌,比如stdio.h什么的
  • extern C,這個我也不是特別理解灼狰,自我修養(yǎng)里面說是聲明為C語言宛瞄,然而刪掉過后就炸了
  • jstring,返回值類型
  • Java_com_helloworld_jnidemo_MainActivity_stringFromJNI交胚,Java_包名類名方法名份汗,這是函數(shù)聲明的規(guī)范
  • JNIEnv *env, jobject /* this */盈电,JNIEnv里面有巨量的函數(shù),后面就知道了杯活,jobject就是this
  • std::string hello = "Hello from C++";匆帚,C艸
  • env->NewStringUTF(hello.c_str()),這兒就出現(xiàn)了env的其中一個函數(shù)旁钧,這個函數(shù)會經(jīng)常在后面用到吸重,char*轉(zhuǎn)String,沒錯歪今,他們不一樣嚎幸!

然后我自己寫了一個HelloWordl和求和的函數(shù):

extern "C"
jstring
Java_com_helloworld_jnidemo_MainActivity_helloworld(JNIEnv *env, jobject /* this */) {
    return env->NewStringUTF("Hello World");
}

extern "C"
jint
Java_com_helloworld_jnidemo_MainActivity_sum(JNIEnv *env, jobject /* this */, jint a, jint b) {
    return a + b;
}

Java中該這樣寫:

static {
    System.loadLibrary("native-lib");
}

public native String stringFromJNI();

public native String helloworld();

其中,System.loadLibrary("native-lib");這句是加載庫彤委,static語句塊中的內(nèi)容只會被執(zhí)行一次鞭铆。native-lib為庫的名稱,聲明方法時使用native關(guān)鍵字焦影。

CMakeLists.txt:

add_library( 
            native-lib
            SHARED
            src/main/cpp/native-lib.cpp )
find_library( 
            log-lib
            log )
target_link_libraries(
                    native-lib
                    ${log-lib} )

其中车遂,native-lib可以隨便改,對應(yīng)System.loadLibrary("native-lib");里面的斯辰。但是有個玄學(xué)問題舶担,不能改成test。彬呻。衣陶。被坑了。闸氮。剪况。
src/main/cpp/native-lib.cpp里面的文件名可以隨便改,只要與你寫的文件對應(yīng)蒲跨。

好的译断,JNI入門了的樣子。

Learn More

寫出來了Hello World或悲,該繼續(xù)深入研究了孙咪。在繼續(xù)之前,我們還應(yīng)該了解一下jstring巡语,jint這些是啥翎蹈,這兒有個表,展示了JNI和Java里面的屬性的關(guān)系:

  • jint --> int
  • jbyte --> byte
  • jshort --> short
  • jlong --> long
  • jfloat --> float
  • jdouble --> double
  • jchar --> char
  • jboolean --> boolean
  • jclass --> java.lang.Class
  • jstring --> java.lang.String
  • jarray --> Array
  • jxxxArray --> xxx[]
  • jobject --> Object
  • ...

注意最后一個男公,一切皆為對象荤堪。

使用JNI,你應(yīng)該實現(xiàn)Java的基本功能:

  • new對象
  • call方法
  • 獲取屬性

學(xué)會了以上三個操作,就可以用JNI代替Java中70%以上的操作了逞力。讓我們一個一個來看曙寡。

new對象 & Call方法

沒錯,new對象就是通過調(diào)用構(gòu)造方法實現(xiàn)的寇荧。

extern "C"
jobject
Java_com_helloworld_asdf_MainActivity_newObject(JNIEnv *env, jobject /* this */) {
    jclass clazz = env->FindClass("java/lang/Object");
    jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
    jobject result = env->NewObject(clazz, init);
    return result;
}

步驟:

  • 找到class举庶,用/代替.,FindClass的參數(shù)為所在包名
  • 找到對應(yīng)構(gòu)造方法
  • 調(diào)用newObject揩抡,傳入class和構(gòu)造方法id户侥。

再看看一般的方法調(diào)用:

extern "C"
jint
Java_com_helloworld_asdf_MainActivity_stringLen(JNIEnv *env, jobject /* this */, jstring str) {
    jclass clazz = env->GetObjectClass(str);
    jmethodID lenId = env->GetMethodID(clazz, "length", "()I");
    jint result = env->CallIntMethod(str, lenId);
    return result;
}

GetObjectClass可以直接從object中拿到class。

調(diào)用方法用CallxxxMethod峦嗤,xxx為返回值類型蕊唐。CallxxxMethod的第一個參數(shù)是jobject,不是jclass烁设,這個與NewObject不同替梨。前面有jxxxArray,然而并沒有CallxxxArrayMethod哎装黑,該怎么辦呢副瀑?一切都是對象,用CallObjectMethod再強轉(zhuǎn)就可以了恋谭。
比如:

extern "C"
jstring
Java_com_helloworld_asdf_MainActivity_toString(JNIEnv *env, jobject /* this */, jobject object) {
    jclass clazz = env->GetObjectClass(object);
    jmethodID lenId = env->GetMethodID(clazz, "toString", "()Ljava/lang/String;");
    jstring result = (jstring) env->CallObjectMethod(object, lenId);
    return result;
}

方法簽名:
簡直有毒糠睡,反人類

  • construction --> <init>
  • void --> V
  • boolean --> Z
  • byte --> B
  • char --> C
  • short --> S
  • int --> I
  • long --> J
  • float --> F
  • double --> D
  • x[] --> [x
  • x[][] --> [[x
  • java.lang.String --> L/java/lang/String;

總結(jié)一下:

  • 每個基本類型都有對應(yīng)的簽名,基本法
  • 數(shù)組用[
  • 構(gòu)造方法規(guī)定為<init>
  • 其它類為L類;疚颊,注意:分號不能丟狈孔,分號不能丟,分號不能丟

獲取Field

extern "C"
jint
Java_com_helloworld_asdf_MainActivity_getX(JNIEnv *env, jobject /* this */, jobject test) {
    jclass clazz = env->GetObjectClass(test);
    jfieldID lenId = env->GetFieldID(clazz, "x", "I");
    jint result = env->GetIntField(test, lenId);
    return result;
}

static

static的屬性和方法與普通的有一些區(qū)別材义,例如CallStaticObjectMethod的第一個參數(shù)是jclass均抽。這些在熟悉了上面的操作過后都沒有太大的問題了。

分享一點經(jīng)驗

  • 一切都是object
  • Java里的String和C(艸)里的是不一樣的其掂,要記得NewStringUTF油挥,被坑過
  • L/java/lang/String;
  • java/util/Listjava/util/ArrayList是不一樣的。清寇。喘漏。要看清方法的參數(shù)护蝶。勋篓。儒旬。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子摇予,更是在濱河造成了極大的恐慌叁熔,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異返十,居然都是意外死亡,警方通過查閱死者的電腦和手機椭微,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門洞坑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蝇率,你說我怎么就攤上這事迟杂。” “怎么了本慕?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵排拷,是天一觀的道長。 經(jīng)常有香客問我锅尘,道長监氢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任藤违,我火速辦了婚禮浪腐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纺弊。我一直安慰自己牛欢,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布淆游。 她就那樣靜靜地躺著傍睹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪犹菱。 梳的紋絲不亂的頭發(fā)上拾稳,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音腊脱,去河邊找鬼访得。 笑死,一個胖子當(dāng)著我的面吹牛陕凹,可吹牛的內(nèi)容都是我干的悍抑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼杜耙,長吁一口氣:“原來是場噩夢啊……” “哼搜骡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佑女,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤记靡,失蹤者是張志新(化名)和其女友劉穎谈竿,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體摸吠,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡空凸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了寸痢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呀洲。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖啼止,靈堂內(nèi)的尸體忽然破棺而出两嘴,到底是詐尸還是另有隱情,我是刑警寧澤族壳,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布憔辫,位于F島的核電站,受9級特大地震影響仿荆,放射性物質(zhì)發(fā)生泄漏贰您。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一拢操、第九天 我趴在偏房一處隱蔽的房頂上張望锦亦。 院中可真熱鬧,春花似錦令境、人聲如沸杠园。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抛蚁。三九已至,卻和暖如春惕橙,著一層夾襖步出監(jiān)牢的瞬間瞧甩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工弥鹦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肚逸,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓彬坏,卻偏偏與公主長得像朦促,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子栓始,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容