眾所皆知,Java是一種可以跨平台的程式語言,而JNI是可以讓Java applications跟用其它語言(諸如C,C++)寫成的應用程式或程式庫互相呼叫使用。
JNI技術的出現主要基於三個方面的應用需求:
A.解決效能問題。
B.解決周邊硬體介面呼叫問題或解決標準JAVA預設函式庫中支援你的應用程式所需的平台相關的功能。。
C.可沿用已開發過的C語言,不須重複開發移植到Java系統。
由於有C/C++的成分存在,因此JNI就失去了跨平台使用,例如從Microsoft要移植到Linux的話,C/C++的部分就必須重新修改編譯過。
以下整理了JAVA呼叫C、C呼叫JAVA兩種HelloWorld教學,大致上應該可以了解一些JNI的觀念。
實作環境:
Ubuntu 10.10
Java 1.6.0_23
gcc 4.4.5
(本次實作在PC上執行)
實作一、JAVA呼叫C
下圖是JNI中JAVA呼叫C的編譯過程:
整個過程中第5步驟如果在Linux下產生的是 .so檔案,如果是windows環境下則可以用Microsoft Visual C++產生出 .dll檔案同樣也可以使用。
Step 1: Write the Java Code
建立HelloWorld.java
Step 2: Compile the Java Code
執行javac HelloWorld.java //編譯
Step 3: Create the .h File (這是自動產生出的不要去編輯)
javah -jni HelloWorld //自動產生對應C標頭檔,內容中粗體為C的函式宣告:
Step 4: Write the Native Method Implementation
建立jni.c
Step 5: Create a Shared Library
執行
gcc -fPIC -shared -I<jni.h 目錄> -I<jni_md.h目錄> jni.c -o libjni.so
在實作中我下的指令如下:
gcc -fPIC -shared -I/usr/local/jdk1.6.0_23/include -I/usr/local/jdk1.6.0_23/include/linux jni.c -o libjni.so
Step 6: Run the Program
執行:
LD_LIBRARY_PATH=`pwd` java HelloWorld
完成。
實作二、C呼叫JAVA
Step 1: Write the Java Code
建立HelloWorld.java
Step 2: Compile the Java Code
執行javac HelloWorld.java //編譯
Step 3: Write the C Code
建立 Invoke.c
Step 4: Compile the C Code
執行
gcc -I<jni.h 目錄> -I<jni_md.h目錄> -L<libjvm.so目錄> -ljvm Invoke.c -o Invoke
在實作中我下的指令如下:
gcc -I/usr/local/jdk1.6.0_23/include -I/usr/local/jdk1.6.0_23/include/linux -L/usr/local/jdk1.6.0_23/jre/lib/amd64/server -ljvm Invoke.c -o Invoke
Step 5: Run the C Program
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/jdk1.6.0_23/jre/lib/amd64/server"
./Invoke
完成。
註:如果執行中見下列錯誤訊息則代表沒有執行步驟5 export ...... (冒號後接的是 libjvm.so 的目錄)
./Invoke: error while loading shared libraries: libjvm.so: cannot open shared object file: No such file or directory
本文內容並非在Android平台執行,主要是寫出我學習Native開發的筆記分享,對於本身不熟JNI的再加上Android部分我覺得多少會提高入門的門檻,因此時間的允許情況下我計畫寫成觀念篇、實戰篇及Android實戰篇,由於本身對於JNI觀念也處於學習中,文章的部分有時間就慢慢來完成了。
參考:
JNI Wiki
http://en.wikipedia.org/wiki/Java_Native_Interface
Lesson: Compiling and Running a Java Program with a Native Method
http://www.cs.rtu.lv/PharePub/Java/Tutorial/native1.1/stepbystep/Default.htm
Trail: Java Native Interface
http://www.cs.rtu.lv/PharePub/Java/Tutorial/native1.1/Default.htm
===========延伸閱讀========================================
第一支Android NDK程式--HelloJni
Java Native Interface (JNI) 的使用時機及影響
Java Native Interface (JNI)入門 -- 觀念篇
Java Native Interface (JNI) 實戰篇
Java Native Interface (JNI) Android實戰篇(使用NDK) -- HelloUart
Java Native Interface (JNI) Android算數篇(使用NDK) -- Fibonacci Sequence
Java Native Interface (JNI) Android C++語言篇--以Hello-JNI為例
Java Native Interface (JNI) Android C++語言篇--以Hello-JNI為例
Java Native Interface (JNI) Android C程式間傳遞篇--以two-libs為例
Java Native Interface (JNI) Android C呼叫Java (底層呼叫上層)間傳遞篇--以靜態或動態類型為例
Android NDK Beginner’s Guide
===========相關閱讀========================================
在 Ubuntu 12.04 LTS 安裝 Android SDK&NDK 開發環境
JAVA呼叫C的實作中
回覆刪除我想請問在STEP3
Create the .h File
文章中提到會自動產生.h檔
但我執行javah -jni Location後
卻只產生下列訊息
請問我該如何解決 謝謝
Exception in thread "main" java.io.IOException: can't find class file Location.class in java.net.URLClassLoader{urls=[file:/usr/lib/jvm/java-1.5.0-gcj-4.5/jre/lib/rt.jar], parent=gnu.gcj.runtime.SystemClassLoader{urls=[file:./], parent=gnu.gcj.runtime.ExtensionClassLoader{urls=[], parent=null}}}
at gnu.classpath.tools.javah.Main.getClass(libgcj-tools.so.11)
at gnu.classpath.tools.javah.Main.run(libgcj-tools.so.11)
at gnu.classpath.tools.javah.Main.main(libgcj-tools.so.11)
從訊息中:can't find class file Location.class
回覆刪除我的解讀是應該是沒找到Location.class檔案,您在確認看看^^
我執行完javac的指令後
回覆刪除在.java的資料夾中有出現.class的檔案
蚊子你好 我想請問一下,
回覆刪除jni 有對應Camera的簽名嗎@@?我不知道要用哪個,順便再請問一下,多個簽名要如何寫?
例如public void f(byte[] byte,Camera camera)
您好,我執行Java Call C第四個步驟,出現錯誤訊息如下:
回覆刪除jni.c:1: fatal error: jni.h: No such file or directory
compilation terminated
請問會是哪裡出錯?謝謝。
按照上面寫的路徑,是在usr/local/底下,但是我的路徑是在/usr/lib底下均多,所以我改了路徑在去執行第四個步驟就成功了.
刪除請問,LD_LIBRARY_PATH=`pwd` java HelloWorld的pwd是固定的嗎?
回覆刪除因為我執行後會出現很多錯誤訊息:java.lang.noclassdeffounderror