原創(chuàng)作品,允許轉(zhuǎn)載朦肘,轉(zhuǎn)載時請務必以超鏈接形式標明文章 原始出處 秩霍、作者信息和本聲明耸别。否則將追究法律責任。http://ticktick.blog.51cto.com/823160/1360240
Android開發(fā)中,經(jīng)常會在Java代碼與Jni層之間傳遞數(shù)組(byte[]),一個典型的應用是Java層把需要發(fā)送給客戶端的數(shù)據(jù)流傳遞到Jni層,由Jni層的Socket代碼發(fā)送出去赁项,當然,Jni層也需要把從Socket接收到的數(shù)據(jù)流返回給Java層澈段。我簡單地總結(jié)了一下悠菜,從Java層到Jni層,從Jni層到JAVA層败富,各有3種傳遞方式悔醋,下面用代碼示例簡單地介紹一下。
示例代碼的主要文件有兩個兽叮,一個是Native.java芬骄,是Java層的類;另一個是Native.c鹦聪,是JNI層的文件账阻,關鍵的地方我都用注釋添加到代碼中了,完整的代碼見博文后面的附件泽本。
一淘太、 從Java傳遞數(shù)組到Jni層
Jni層接收到Java層傳遞過來的byte[]數(shù)組,一般有2個函數(shù)來獲取它的值规丽,一個 GetByteArrayRegion蒲牧,另一個是 GetByteArrayElements ,前者是進行值拷貝赌莺,將Java端數(shù)組的數(shù)據(jù)拷貝到本地的數(shù)組中冰抢,后者是指針的形式,將本地的數(shù)組指針直接指向Java端的數(shù)組地址艘狭,其實本質(zhì)上是JVM在堆上分配的這個數(shù)組對象上增加一個引用計數(shù)挎扰,保證垃圾回收的時候不要釋放翠订,從而交給本地的指針使用,使用完畢后指針一定要記得通過ReleaseByteArrayElements進行釋放遵倦,否則會產(chǎn)生內(nèi)存泄露尽超。
首先看Native.java的定義:
再看看對應的native.c的實現(xiàn)代碼:
二、 從Jni層傳遞數(shù)組到Java層
把Jni層定義的數(shù)組傳遞到Java層骇吭,一般有兩種方法橙弱,一種是通過native函數(shù)的返回值來傳遞歧寺,另一種是通過jni層回調(diào)java層的函數(shù)來傳遞燥狰,后者多用于jni的線程中。無論哪種方法斜筐,都離不開 SetByteArrayRegion 函數(shù)龙致,該函數(shù)將本地的數(shù)組數(shù)據(jù)拷貝到了 Java 端的數(shù)組中。下面只介紹前一種方式顷链,即通過native函數(shù)返回值的方式傳遞jni層的數(shù)組目代,回調(diào)的方式其實用法類似,就不詳細介紹了嗤练。
首先看Native.java的定義:
再看看native.c是如何實現(xiàn)的:
由上述代碼示例可以看出榛了,首先通過 NewByteArray 在堆上分配數(shù)組對象,然后通過SetByteArrayRegion 把本地的數(shù)組數(shù)據(jù)拷貝到堆上分配的數(shù)組中去煞抬,然后通過返回值將分配的數(shù)組對象返回到Java層即可霜大。對于回調(diào)的方式,這幾步操作也是一樣的革答,唯一的不同是战坤,回調(diào)方式不是以返回值的方式將數(shù)組對象返回給Java層,而是在回調(diào)函數(shù)中残拐,以回調(diào)函數(shù)參數(shù)的形式返回給Java層途茫。
三、 Direct Buffer 方式傳遞
Java和Jni層的數(shù)組傳遞還有一個比較重要的方式溪食,就是通過Direct Buffer來傳遞囊卜,這種方式類似于在堆上創(chuàng)建創(chuàng)建了一個Java和Jni層共享的整塊內(nèi)存區(qū)域,無論是Java層或者Jni層均可訪問這塊內(nèi)存错沃,并且Java端與Jni端同步變化边败,由于是采用的是共享內(nèi)存的方式,因此相比于普通的數(shù)組傳遞捎废,效率更高笑窜,但是由于構(gòu)造/析構(gòu)/維護這塊共享內(nèi)存的代價比較大,所以小數(shù)據(jù)量的數(shù)組建議還是采用上述方式登疗,Direct Buffer方式更適合長期使用頻繁訪問的大塊內(nèi)存的共享排截。具體使用方法介紹如下:
首先看Native.java的定義:
再看看native.c是如何實現(xiàn)的:
由上述代碼可以看出嫌蚤,其中使用起來還是很簡單的,Jni層只需要通過GetDirectBufferAddress函數(shù)即可獲取到這塊共享的內(nèi)存的地址断傲,Direct Buffer的管理工作均由操作系統(tǒng)來負責脱吱。
四、 總結(jié)
關于Java與Jni層的數(shù)組傳遞就介紹到這里了认罩,其實并不復雜箱蝠,希望上述代碼對初學者能有所幫助,有任何疑問或者不清楚的地方歡迎留言或者來信lujun.hust@gmail.com交流垦垂,或者關注我的新浪微博 @盧_俊 獲取最新的文章和資訊宦搬。