嗝额 不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”,看它的示例:
Example
The 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 −
Linux
libos.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文件中引用你用到的系统库或者本地库,否则会报编译错误!
比较粗糙,等有时间了再来整理,希望这篇文章能够帮助朋友们少踩一点莫名其妙的坑。再见