JNA(Java Native Access):建立在JNI之上的Java開源框架,SUN主導開發,用來調用C、C++代碼,尤其是底層庫文件(windows中叫dll文件,linux下是so【shared object】文件)。
JNI是Java調用原生函數的唯一機制,JNA就是建立在JNI之上,JNA簡化了Java調用原生函數的過程。JNA提供了一個動態的C語言編寫的轉發器(實際上也是一個動態鏈接庫,在Linux-i386中文件名是:libjnidispatch.so)可以自動實現Java與C之間的數據類型映射。從性能上會比JNI技術調用動態鏈接庫要低。
筆者機器中libvirt相關的動態鏈接庫:
lzjun@lzjun-ubuntu:/var/run/libvirt$ ll /usr/lib/libvirt
libvirt/ libvirt-qemu.so.0.9.8 libvirt.so.0.9.8
libvirt-qemu.so.0 libvirt.so.0
libvirt/ libvirt-qemu.so.0.9.8 libvirt.so.0.9.8
libvirt-qemu.so.0 libvirt.so.0
實例:(筆者環境:Ubuntu1204、JDK6、gcc)
一:編寫動態鏈接庫:(庫文件名格式:lib*.so*)
1、編寫頭文件 #hellworld.h
- void test();
- #include<stdio.h>
- void test(){
- printf("helloworld\n");
- }
gcc -fpic -shared -o libhello.so helloworld.c
文件libhello.so生成。(此處還有一步,請看文章結尾處的異常),接下來就可以編寫測試文件調用該動態鏈接庫了。
二:編寫測試文件
如果是用maven構建項目,非maven項目google之,把jna.jar加入classpath即可,JNA 的包依賴:
- <dependency>
- <groupId>com.sun.jna</groupId>
- <artifactId>jna</artifactId>
- <version>3.0.9</version>
- </dependency>
編寫測試類:
- import com.sun.jna.Library;
- import com.sun.jna.Native;
- public class JnaTest {
- //繼承Library,用於加載庫文件
- public interface Clibrary extends Library{
- //加載libhello.so鏈接庫
- Clibrary INSTANTCE = (Clibrary) Native.loadLibrary("hello", Clibrary.class);
- //此方法為鏈接庫中的方法
- void test();
- }
- public static void main(String[] args) {
- //調用
- Clibrary.INSTANTCE.test();
- }
- }
#輸出“helloworld”
如果拋出如下異常:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'hello': libhello.so: cannot open shared object file: No such file or directory
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:145)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:188)
at com.sun.jna.Library$Handler.<init>(Library.java:123)
at com.sun.jna.Native.loadLibrary(Native.java:255)
at com.sun.jna.Native.loadLibrary(Native.java:241)
at JnaTest$Clibrary.<clinit>(JnaTest.java:12)
at JnaTest.main(JnaTest.java:22)
那是JVM沒法找到動態鏈接庫的路徑,此時需要把動態鏈接庫加入系統的/lib目錄或修改配置文件:
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:145)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:188)
at com.sun.jna.Library$Handler.<init>(Library.java:123)
at com.sun.jna.Native.loadLibrary(Native.java:255)
at com.sun.jna.Native.loadLibrary(Native.java:241)
at JnaTest$Clibrary.<clinit>(JnaTest.java:12)
at JnaTest.main(JnaTest.java:22)
# pwd >> /etc/ld.so.conf (把動態鏈接庫所在路徑加入配置文件中,此處用pwd是因為筆者當前所在目錄就是鏈接庫文件所在目錄)
# ldconfig
參考:http://blog.csdn.net/laomai/article/details/1510957
http://liuzhijun.iteye.com/blog/1744630