溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JNI在Android中的簡單使用

發(fā)布時間:2020-06-07 16:18:54 來源:網(wǎng)絡 閱讀:399 作者:nineteens 欄目:編程語言

  JNI是什么

  JNI是java平臺的一個特性(與Android無關(guān))

  英文參考文檔中的介紹如下:

  The Java? Native Interface (JNI) is a powerful feature of the Java platform.

  Applications that use the JNI can incorporate native code written in programming

  languages such as C and C++, as well as code written in the Java programming

  language. The JNI allows programmers to take advantage of the power of the Java

  platform, without having to abandon their investments in legacy code. Because the

  JNI is a part of the Java platform, programmers can address interoperability issues

  once, and expect their solution to work with all implementations of the Java plat-

  form.

  JDK環(huán)境搭建

  想要使用jni,需要搭建好jdk環(huán)境。

  jdk-8u211-linux-x64.tar.gz 的下載地址:

  https://download.oracle.com/otn/java/jdk/8u211-b12/478a62b7d4e34b78b671c754eaaf38ab/jdk-8u211-linux-x64.tar.gz?AuthParam=1559785898_96645c696d32befddea78681f9c1926f

  把jdk-8u211-linux-x64.tar.gz解壓到/usr/local/jdk目錄下,然后修改~/.bashrc文件,在該文件最后面,添加如下內(nèi)容:

  #JDK

  export PATH=/usr/local/jdk/jdk1.8.0_211/bin/:$PATH

  然后使用 source ~/.bashrc命令更新環(huán)境變量。

  判斷環(huán)境是否配置成功:

  root@ubuntu:/usr/local/jdk# java -version

  java version "1.8.0_211"

  Java(TM) SE Runtime Environment (build 1.8.0_211-b12)

  Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)

  root@ubuntu:/usr/local/jdk#

  如所示,jdk環(huán)境搭建完成。

  使用流程:

  JNI測試

  下面介紹jni的測試過程。

  HelloWorld.java 文件

  新建 HelloWorld.java文件,并填充代碼如下。

  class HelloWorld {

  private native void print();

  public static void main(String[] args) {

  new HelloWorld().print();

  }

  static {

  System.loadLibrary("HelloWorld");

  }

  }

  使用如下命令編譯,生成 HelloWorld.class文件:

  root@ubuntu:~/ken/jni# javac HelloWorld.java

  root@ubuntu:~/ken/jni# ls

  HelloWorld.class HelloWorld.java

  root@ubuntu:~/ken/jni#

  HelloWorld.h 文件

  使用如下命令編譯,生成HelloWorld.h文件。之后根據(jù)該.h文件,編寫jni的.c文件。

  root@ubuntu:~/ken/jni# ls

  HelloWorld.class HelloWorld.java

  root@ubuntu:~/ken/jni# javah -jni HelloWorld

  root@ubuntu:~/ken/jni# ls

  HelloWorld.class HelloWorld.h HelloWorld.java

  root@ubuntu:~/ken/jni#

  打開HelloWorld.h文件,內(nèi)容如下:

  /* DO NOT EDIT THIS FILE - it is machine generated */

  #include

  /* Header for class HelloWorld */

  #ifndef _Included_HelloWorld

  #define _Included_HelloWorld

  #ifdef __cplusplus

  extern "C" {

  #endif

  /*

  * Class: HelloWorld

  * Method:print

  * Signature: ()V

  */

  JNIEXPORT void JNICALL Java_HelloWorld_print

  (JNIEnv *, jobject);

  #ifdef __cplusplus

  }

  #endif

  #endif

  HelloWorld.c 文件

  則我們編寫HelloWorld.c文件如下:

  #include

  #include

  #include "HelloWorld.h"

  JNIEXPORT void JNICALL

  Java_HelloWorld_print(JNIEnv *env, jobject obj)

  {

  printf("Hello World!\n");

  return;

  }

  libHelloWorld.so 動態(tài)庫文件

  接下來,把HelloWorld.c文件編譯成動態(tài)庫:libHelloWorld.so即可。

  PS:

  1、此處編譯出的動態(tài)庫的名稱,是HelloWorld.java文件中定義了的。

  System.loadLibrary(“HelloWorld”);

  上面這條程序的作用就是加載libHelloWorld.so庫文件。

  2、在HelloWorld.h文件中函數(shù)聲明是:

  JNIEXPORT void JNICALL Java_HelloWorld_print

  (JNIEnv *, jobject);

  在HelloWorld.c文件中函數(shù)定義為:

  JNIEXPORT void JNICALL

  Java_HelloWorld_print(JNIEnv *env, jobject obj)

  如果函數(shù)參數(shù)中沒有定義*env和obj,則會在編譯庫時報錯:

  HelloWorld.c: In function ‘Java_HelloWorld_print’:

  HelloWorld.c:6:1: error: parameter name omitted

  Java_HelloWorld_print(JNIEnv, jobject)

  ^

  HelloWorld.c:6:1: error: parameter name omitted

  3、筆者這邊是在linux環(huán)境下測試的。如果是windwows的話,編譯出.dll文件。

  接下來,編譯出動態(tài)庫:

  root@ubuntu:~/ken/jni# gcc -shared -fPIC -Wall HelloWorld.c -o libHelloWorld.so

  HelloWorld.c:1:17: fatal error: jni.h: No such file or directory

  #include

  ^

  compilation terminated.

  root@ubuntu:~/ken/jni#

  如上,報錯顯示找不到動態(tài)庫。

  此時就和之前的jdk環(huán)境搭建有關(guān)系了。

  root@ubuntu:~/ken/jni# ls /usr/local/jdk/jdk1.8.0_211/include/

  classfile_constants.h jawt.h jdwpTransport.h jni.h jvmticmlr.h jvmti.h linux

  root@ubuntu:~/ken/jni#無錫人流多少錢 http://www.bhnfkyy.com/

  我們發(fā)現(xiàn),在jdk中有我們需要的jni.h文件。

  現(xiàn)在我們有兩種方式可以解決這個報錯。

  第一種是把#include 改為#include "jni.h",然后把jdk中的jni.h文件拷貝到當前目錄下。

  第二種是在編譯時通過“-I加頭文件路徑”,讓編譯器找到jni.h文件。

  我們使用第二種。

  繼續(xù)編譯動態(tài)庫。

  root@ubuntu:~/ken/jni# gcc -shared -fPIC -Wall -I/usr/local/jdk/jdk1.8.0_211/include HelloWorld.c -o libHelloWorld.so

  In file included from HelloWorld.c:1:0:

  /usr/local/jdk/jdk1.8.0_211/include/jni.h:45:20: fatal error: jni_md.h: No such file or directory

  #include "jni_md.h"

  ^ 

  compilation terminated.

  root@ubuntu:~/ken/jni#

  報錯找不到jni_md.h文件。如果查看jni.h文件的話,會發(fā)現(xiàn)里面有包含jni_md.h文件。

  jni_md.h文件在:(使用grep命令,在jdk目錄下搜索)

  root@ubuntu:~/ken/jni# ls /usr/local/jdk/jdk1.8.0_211/include/linux/

  jawt_md.h jni_md.h

  root@ubuntu:~/ken/jni#

  把該路徑添加到-I參數(shù),繼續(xù)編譯動態(tài)庫。

  root@ubuntu:~/ken/jni# gcc -shared -fPIC -Wall -I/usr/local/jdk/jdk1.8.0_211/include -I/usr/local/jdk/jdk1.8.0_211/include/linux HelloWorld.c -o libHelloWorld.so

  root@ubuntu:~/ken/jni# ls

  HelloWorld.c HelloWorld.class HelloWorld.h HelloWorld.java jni.h libHelloWorld.so

  root@ubuntu:~/ken/jni#

  成功編譯出libHelloWorld.so動態(tài)庫。

  測試JNI程序

  root@ubuntu:~/ken/jni# ls

  HelloWorld.c HelloWorld.class HelloWorld.h HelloWorld.java jni.h libHelloWorld.so

  root@ubuntu:~/ken/jni# java HelloWorld

  Hello World!

  root@ubuntu:~/ken/jni#

  成功運行C代碼中函數(shù)。

  ————————————————————————————————

  上面只是簡單的jni調(diào)用,了解jni的大致調(diào)用流程。

  關(guān)于JNI還有很多需要了解的,比如參數(shù)類型、函數(shù)傳參等。

  —————————————————————————————————

  需要強調(diào)的是,雖然jni和ndk經(jīng)常一起使用。但是jni是jni,ndk是ndk,是兩碼事。

  什么時候需要ndk呢?用到Android時,就需要ndk了。

  上面編譯動態(tài)庫的過程也不是通過gcc編譯了,而是使用ndk提供的ndk-build工具,編譯出動態(tài)庫,給apk調(diào)用。


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI