自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android架構(gòu)師之路-JNI與NDK編程知識(shí)基礎(chǔ)詳解(c++音視頻編碼基礎(chǔ))

開發(fā) 前端
NDK提供了一系列的工具,幫助開發(fā)者快速開發(fā)C(或C++)的動(dòng)態(tài)庫,并能自動(dòng)將so和java應(yīng)用一起打包成apk。這些工具對(duì)開發(fā)者的幫助是巨大的。

[[412121]]

前沿小記

  • 1、Android架構(gòu)師要學(xué)習(xí)的知識(shí)點(diǎn)有很多,后面我會(huì)總結(jié)下關(guān)于Android開發(fā)中jni和ndk開發(fā)的知識(shí)點(diǎn),當(dāng)前基礎(chǔ)是越牢固越好,后期學(xué)習(xí)起來就不會(huì)太累,一點(diǎn)就懂;
  • 2、今天我們就來總結(jié)下jni和ndk的基礎(chǔ)知識(shí)點(diǎn);
  • 3、Android 平臺(tái)從一開就已經(jīng)支持了C/C++了。我們知道Android的SDK主要是基于Java的,所以導(dǎo)致了在用Android SDK進(jìn)行開發(fā)的工程師們都必須使用Java語言。不過,Google從一開始就說明Android也支持JNI編程方式,也就是第三方應(yīng)用完成可以通過JNI調(diào)用自己的C動(dòng)態(tài)度;

一、什么是ndk

  • NDK提供了一系列的工具,幫助開發(fā)者快速開發(fā)C(或C++)的動(dòng)態(tài)庫,并能自動(dòng)將so和java應(yīng)用一起打包成apk。這些工具對(duì)開發(fā)者的幫助是巨大的;
  • NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU、平臺(tái)、ABI等差異,開發(fā)人員只需要簡(jiǎn)單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創(chuàng)建出so;
  • NDK可以自動(dòng)地將so和Java應(yīng)用一起打包,極大地減輕了開發(fā)人員的打包工作;
  • NDK提供了一份穩(wěn)定、功能有限的API頭文件聲明;Google明確聲明該API是穩(wěn)定的,在后續(xù)所有版本中都穩(wěn)定支持當(dāng)前發(fā)布的API。從該版本的NDK中看出,這些API支持的功能非常有限,包含有:C標(biāo)準(zhǔn)庫(libc)、標(biāo)準(zhǔn)數(shù)學(xué)庫(libm)、壓縮庫(libz)、Log庫(liblog);
  • NDK的發(fā)布,使“Java+C”的開發(fā)方式終于轉(zhuǎn)正,成為官方支持的開發(fā)方式;
  • 使用NDK,我們可以將要求高性能的應(yīng)用邏輯使用C開發(fā),從而提高應(yīng)用程序的執(zhí)行效率;
  • 使用NDK,我們可以將需要保密的應(yīng)用邏輯使用C開發(fā)。畢竟,Java包都是可以反編譯的;
  • NDK促使專業(yè)so組件商的出現(xiàn):比如視頻庫的編譯、音頻庫、圖片庫濾鏡等等;
  • NDK將使Android平臺(tái)支持C開發(fā)的開端;NDK提供了的開發(fā)工具集合,使開發(fā)人員可以便捷地開發(fā)、發(fā)布C組件。同時(shí),Google承諾在NDK后續(xù)版本中提高“可調(diào)式”能力,即提供遠(yuǎn)程的gdb工具,使我們可以便捷地調(diào)試C源碼;

二、為什么使用NDK

在平臺(tái)之間移植其應(yīng)用;

重復(fù)使用現(xiàn)在庫,或者提供其自己的庫重復(fù)使用;

在某些情況下提性能,特別是像游戲這種計(jì)算密集型應(yīng)用;

使用第三方庫,現(xiàn)在許多第三方庫都是由C/C++庫編寫的,比如Ffmpeg這樣庫;

不依賴于Dalvik Java虛擬機(jī)的設(shè)計(jì);

代碼的保護(hù)。由于APK的Java層代碼很容易被反編譯,而C/C++庫反編譯難度大;

三、jni詳解

1、jni是什么?以及和ndk關(guān)系

  • JNI,全稱為Java Native Interface,即Java本地接口,JNI是Java調(diào)用Native 語言的一種特性。通過JNI可以使得Java與C/C++機(jī)型交互。即可以在Java代碼中調(diào)用C/C++等語言的代碼或者在C/C++代碼中調(diào)用Java代碼。由于JNI是JVM規(guī)范的一部分,因此可以將我們寫的JNI的程序在任何實(shí)現(xiàn)了JNI規(guī)范的Java虛擬機(jī)中運(yùn)行;
  • 在Android Framework中,需要提供一種媒介或 橋梁,將Java層(上層)與C/C++層(下層)有機(jī)的聯(lián)系起來,使得他們互相協(xié)調(diào)完成某些任務(wù)。而充當(dāng)這種媒介的就是Java本地接口(JNI,Java Native Interface);
  • JNI提供一些列的接口,允許Java類與C/C++等本地編輯語言(在JNI中,這些語言被稱為 本地語言)編寫的應(yīng)用 程序、模塊 、庫進(jìn)行交互操作。比如,在Java類中使用C語言庫中的函數(shù)或在C語言中使用 Java類庫,都需要借助JNI;
  • Android NDK是一個(gè)開發(fā)工具集,提供一系列工具快速開發(fā)C/C++的動(dòng)態(tài)庫,并能自動(dòng)將 .so/.dll 和 Java 應(yīng)用一起打包到Apk;NDK提供工具可以方便JNI調(diào)用C/C++,而且提供了交叉編譯器可以修改.mk文件生成特定CPU平臺(tái)的動(dòng)態(tài)庫,并能將so和java應(yīng)用一起打包到apk中;簡(jiǎn)單說就是JNI負(fù)責(zé)Java與C/C++進(jìn)行互相操作,NDK提供工具方便在Android平臺(tái)使用JNI;

2、JNI開發(fā)流程的步驟

圖片
  • 在Java中先聲明一個(gè)native方法;
  • 編譯Java源文件javac得到.class文件;
  • 通過javah -jni命令導(dǎo)出JNI的.h頭文件;
  • 使用Java需要交互的本地代碼,實(shí)現(xiàn)在Java中聲明的Native方法;
  • 將本地代碼編譯成動(dòng)態(tài)庫(Windows系統(tǒng)下是.dll文件,如果是Linux系統(tǒng)下是.so文件,如果是Mac系統(tǒng)下是.jnilib);
  • 通過Java命令執(zhí)行Java程序,最終實(shí)現(xiàn)Java調(diào)用本地代碼;
圖片

3、 JNI數(shù)據(jù)結(jié)構(gòu)

圖片

JNI函數(shù)表的組成就像C++的虛函數(shù)表。虛擬機(jī)可以運(yùn)行多張函數(shù)表,舉例來說,一張調(diào)試函數(shù)表,另一張是調(diào)用函數(shù)表。JNI接口指針僅在當(dāng)前線程中起作用。這意味著指針不能從一個(gè)線程進(jìn)入另一個(gè)線程,然而,可以在不同的咸亨中調(diào)用本地方法;

  1. jdouble test (JNIEnv *env, jobject obj, jint i, jstring s) 
  2.      const char *str = (*env)->GetStringUTFChars(env, s, 0);  
  3.      (*env)->ReleaseStringUTFChars(env, s, str);  
  4.      return 10; 
圖片

JNI有自己的原始數(shù)據(jù)類型和數(shù)據(jù)引用類型如下

圖片

四、jni交互原理詳解

1、JavaVM

JavaVM是Java虛擬機(jī)在JNI層的代表,JNI全局僅僅有一個(gè)JavaVM結(jié)構(gòu)中封裝了一些函數(shù)指針(或叫函數(shù)表結(jié)構(gòu)),JavaVM中封裝的這些函數(shù)指針主要是對(duì)JVM操作接口。另外,在C和C++中的JavaVM的定義有所不同,在C中JavaVM是JNIInvokeInterface_類型指針,而在C++中有對(duì)JNIInvokeInterface_進(jìn)行了一次封裝,比C中少了一個(gè)參數(shù),這也是為什么JNI代碼更推薦使用C++來編寫的原因;

2、JNIEnv

JNIEnv是一個(gè)線程相關(guān)的結(jié)構(gòu)體,該結(jié)構(gòu)體代表了Java在本線程的執(zhí)行環(huán)境

JNIEnv是當(dāng)前Java線程的執(zhí)行環(huán)境,一個(gè)JVM對(duì)應(yīng)一個(gè)JavaVM結(jié)構(gòu),而一個(gè)JVM中可能創(chuàng)建多個(gè)Java線程,每個(gè)線程對(duì)應(yīng)一個(gè)JNIEnv結(jié)構(gòu),它們保存在線程本地存儲(chǔ)TLS中。因此,不同的線程的JNIEnv是不同,也不能相互共享使用。JNIEnv結(jié)構(gòu)也是一個(gè)函數(shù)表,在本地代碼中通過JNIEnv的函數(shù)表來操作Java數(shù)據(jù)或者調(diào)用Java方法。也就是說,只要在本地代碼中拿到了JNIEnv結(jié)構(gòu),就可以在本地代碼中調(diào)用Java代碼;

調(diào)用Java 函數(shù):JNIEnv代表了Java執(zhí)行環(huán)境,能夠使用JNIEnv調(diào)用Java中的代碼;

操作Java代碼:Java對(duì)象傳入JNI層就是jobject對(duì)象,需要使用JNIEnv來操作這個(gè)Java對(duì)象;

3、JNIEnv和JavaVM的區(qū)別

  • JavaVM:JavaVM是Java虛擬機(jī)在JNI層的代表,JNI全局僅僅有一個(gè);
  • JNIEnv:JavaVM 在線程中的代碼,每個(gè)線程都有一個(gè),JNI可能有非常多個(gè)JNIEnv;

4、JNIEnv與線程

  • JNIEnv是線程相關(guān)的,即在每一個(gè)線程中都有一個(gè)JNIEnv指針,每個(gè)JNIEnv都是線程專有的,其他線程不能使用本線程中的JNIEnv,即線程A不能調(diào)用線程B的JNIEnv,所以JNIEnv不能跨線程;
  • JNIEnv只在當(dāng)前線程有效:JNIEnv僅僅在當(dāng)前線程有效;
  • JNIEnv不能在線程之間進(jìn)行傳遞,在同一個(gè)線程中,多次調(diào)用JNI層方便,傳入的JNIEnv是同樣的;
  • 本地方法匹配多個(gè)JNIEnv:在Java層定義的本地方法,能夠在不同的線程調(diào)用,因此能夠接受不同的JNIEnv;

5、JNIEnv結(jié)構(gòu)

圖片

6、JNIEnv相關(guān)的常用函數(shù)

  1. 創(chuàng)建Java中的對(duì)象 
  2.     jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...); 
  3.     jobject     (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list); 
  4.     jobject     (*NewObjectA)(JNIEnv*, jclass, jmethodID, const jvalue*); 
  5. 字符串相關(guān) 
  6.   jstring     (*NewString)(JNIEnv*, const jchar*, jsize); 
  7.     jsize       (*GetStringLength)(JNIEnv*, jstring); 
  8.     const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); 
  9.     void        (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); 
  10.     jstring     (*NewStringUTF)(JNIEnv*, const char*); 
  11.     jsize       (*GetStringUTFLength)(JNIEnv*, jstring); 
  12.     /* JNI spec says this returns const jbyte*, but that's inconsistent */ 
  13.     const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); 
  14. 獲取數(shù)組相關(guān) 
  15.  jsize GetArrayLength(jarray array) 
  16. return functions->GetArrayLength(this, array); } 
  17. jobject GetObjectArrayElement(JNIEnv *env, 
  18. jobjectArray array, jsize index); 

總結(jié):

  • 以上是學(xué)習(xí)jni的基礎(chǔ)知識(shí)點(diǎn),必須理解的,不懂的就問就學(xué);
  • jni還有很多知識(shí)點(diǎn),比如動(dòng)態(tài)注冊(cè),靜態(tài)注冊(cè)等等;
  • 要學(xué)習(xí)一點(diǎn)c語言和c++的基礎(chǔ)知識(shí)點(diǎn),后面會(huì)講到總結(jié)。

本文轉(zhuǎn)載自微信公眾號(hào)「Android開發(fā)編程」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系A(chǔ)ndroid開發(fā)編程公眾號(hào)。

 

責(zé)任編輯:姜華 來源: Android開發(fā)編程
相關(guān)推薦

2021-07-26 05:26:54

Androidc++java

2023-03-03 15:40:43

抖音視頻編碼器

2011-07-13 18:24:18

C++

2013-04-19 15:12:17

架構(gòu)師WEB架構(gòu)師

2010-02-01 16:13:15

C++繼承

2010-01-19 14:45:35

C++語言

2015-06-10 11:22:41

云計(jì)算云架構(gòu)師

2010-01-19 10:16:40

C++程序

2011-07-15 01:38:56

C++this指針

2010-02-02 09:43:27

C++存儲(chǔ)區(qū)域

2010-02-05 17:00:06

C++單例模式

2020-09-30 09:47:17

架構(gòu)

2011-07-14 17:37:02

C++面向?qū)ο缶幊趟枷?/a>

2011-07-14 17:24:10

C++面向?qū)ο笏枷?/a>

2022-06-20 05:59:35

5G技術(shù)音視頻技術(shù)安卓系統(tǒng)

2009-08-24 18:22:05

C# 泛型編程

2009-04-17 14:22:40

XPathXML基礎(chǔ)

2018-07-03 15:46:24

Java架構(gòu)師源碼

2009-08-21 17:19:36

C#網(wǎng)絡(luò)編程入門

2012-04-09 09:41:24

WEB架構(gòu)師
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)