java調用so


昨天接到個小需求,需要在java中調第三方的so。回想上一次使用jni還是剛畢業那會兒,那時候我還會自己寫C,生成dll和so,然后通過jni來調。慚愧,現在C/C++已經完全不會了…

使用原生的jni開發略麻煩,可以直接基於jna(java native access)這個jar。具體步驟如下:

引入jna的jar

<dependency>
    <groupId>com.sun.jna</groupId>
    <artifactId>jna</artifactId>
    <version>3.0.9</version>
</dependency>

定義一個接口和so中的方法對應

比如我這邊拿到的.h文件為

int decryptToken(const char *sIn, int iInlen);

那么我的java代碼就可以這么寫

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface DecryptLib extends Library {
    DecryptLib INSTANCE = (DecryptLib) Native.loadLibrary("/usr/local/libtoken.so", DecryptLib.class);
    int decryptToken(String encrptyToken, int length);
}

本想把so放在jar里面,省的部署環境的時候容易漏掉。但一直沒找到簡單的方法,網上說了一堆,但是我驗證了不行。一般都還是需要先解壓到某個臨時目錄。

See https://stackoverflow.com/questions/4113317/load-library-from-jar

使用

public class DecryptUtil {
    private static DecryptLib instance = DecryptLib.INSTANCE;

    public static void decrypt(String token) {
        int code = instance.decryptToken(token, token.length());
    }
}

Java和C數據類型對應關系

<這個網上太多了,不抄過來了,_>

可能遇到的問題

(1)提示找不到

java.lang.UnsatisfiedLinkError: Unable to load library 'libtoken': libtoken.so: cannot open shared object file: No such file or directory

這種情況一般都是JVM找不到動態鏈接庫導致的,檢查下路徑。

上面的代碼是寫的so的絕對路徑,如果你寫的相對路徑,並添加了classpath,那么這里只需要寫

DecryptLib INSTANCE = (DecryptLib) Native.loadLibrary("token", DecryptLib.class);

不需要lib前綴,也不需要擴展名.so

(2)提示找不到方法

java.lang.UnsatisfiedLinkError: Error looking up function 'decryptToken': /usr/loca/libtoken.so: undefined symbol: decryptToken

dll/so寫法問題。原因是,C++中,方法必須加上extern “C”,否則無法找到c++方法。

(3)提示沒有GLIBCXX_3.4.18

java.lang.UnsatisfiedLinkError: Unable to load library '/usr/local/libtoken.so': /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by /usr/local/libtoken.so)

這種一般是so需要依賴對應版本的glibcxx,安裝一下就好了。

可以通過【strings /usr/lib64/libstdc++.so.6 | grep GLIBC】命令看下當前linux機器上已有的版本


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM