嗝額 不bb開頭了。時間緊迫。
這兩天一直都在弄JNI的事情,在windows下正常,但是到了liunx下總是報一個錯誤,no xxx on java.library.path,在java.library.path找不到指定的so庫。
感到很奇怪,於是用
System.out.println(System.getProperty("java.library.path"))
列印出java.library.path的路徑。表示我的路徑亂七八糟,遂棄。
一步步調試,到ClassLoader類裡,發現尋找庫的時候檔案會被莫名其妙的拼上一個lib,剛開始以為是路徑沒有配好,後來發現是系統調用了一個方法:java.lang.System.mapLibraryName()罪魁禍首。這個方法會在咱們的給定的名字前拼接上”lib”,看它的樣本:
ExampleThe following example shows the usage of java.lang.System.mapLibraryName() method.package com.tutorialspoint;import java.lang.*;public class SystemDemo { public static void main(String[] args) { // prints the name of the Operating System System.out.println(System.getProperty("os.name")); /* maps a library name into a platform-specific string representing a native library */ String str = System.mapLibraryName("os.name"); System.out.println(str); }} Let us compile and run the above program, this will produce the following result −Linuxlibos.name.so
咱們的載入方法System.loadLibrary("AES128Converter");
完了以後程式真正去找的名字變成了java.library.path下的“libAES128Converter.so”
解決方案就是:
在咱們產生so檔案的時候在前面加上一個”lib”,這樣程式在啟動並執行時候才能找到so檔案,另外就是,liunx下java尋找so庫的路徑為:${你的java_home}/jre/lib/amd64
在產生so庫之前需要得到兩個檔案:jni.h、jni_md.h
他們分別在${你的java_home}/include和${你的java_home}/include/linux下,拷貝他們兩和需要編譯的檔案放在同一個檔案夾後,
在liunx下利用gcc編譯so檔案:
gcc -fPIC -shared -o libHelloWorld.so HelloWorld.c
具體每個選項的意義感興趣的同學可以去自行百度,這裡要說的是,記得在你的.c檔案中引用你用到的系統庫或者本地庫,否則會報編譯錯誤。
比較粗糙,等有時間了再來整理,希望這篇文章能夠協助朋友們少踩一點莫名其妙的坑。再見