java中对jni的调用实例

     什么是jni:jni是java native interface的缩写,是java平台的一部分,允许java代码和其他语言写的代码进行交互。     
     在本模块resource下面或者创建一个模块在resource下面创建目录native/linux/amd64下面放入libhs.so  native/windows/amd64下面放入hyperscan.dll   native/windows/x86下面放入hyperscan.dll或者在maven项目新建一个model直接将文件放入src目录下,调用的时候直接引入该模块即可。
     其中linux代表是linux的jni文件位置,windows/amd64代表是64位的windows的jni文件位置,windows/x86代表32位的windows的jni文件位置
     加载:其中(
     Properties props=System.getProperties();  //获得系统属性集   
     String osName = props.getProperty( "os.name" );  //操作系统名称   
     String osArch = props.getProperty( "os.arch" );  //操作系统构架  (是amd64还是x86) 
     String osVersion = props.getProperty( "os.version" );  //操作系统版本 )
    public class Hyperscan {
    public static final String OSName = System.getProperty("os.name").toLowerCase();
    public static final String ArchName = System.getProperty("os.arch");
    public static final boolean IsWindows = OSName.indexOf("windows") > -1;
    public static final boolean IsLinux = OSName.indexOf("linux") > -1;
    public static final boolean IsMacOs = !IsWindows && !IsLinux;
    public static final String sharedExt = getSharedExtName();
    //方法中native是jni的标识
    public static native int hsExpressionInfo(String express, int flags, PointerWrapper info, PointerWrapper error);

    public static native void hsFreeExpressionInfo(PointerWrapper info);

    public static native void hsFreeCompileError(PointerWrapper error);

    public static native String hsGetErrorMessage(PointerWrapper error);
    public static native int hsGetErrorExpress(PointerWrapper error);

    public static native int hsCreateStringBuffer(final byte[] input, PointerWrapper pointer);

    public static native void hsReleaseStringBuffer(final byte[] input, PointerWrapper pointer);
    
    public static native int hsCompile(String express, int flags, int block, PointerWrapper platform,
            PointerWrapper database, PointerWrapper error);
    public static native int hsCompileMulti(String[] express, int[] flags, int[] ids, int size, int block,
            PointerWrapper platform, PointerWrapper database, PointerWrapper error);
    
    public static native int hsDeserializeDatabase(byte[] data,  int off, int length, PointerWrapper database);
    public static native int hsGetDatabaseSize(PointerWrapper database);
    public static native byte[] hsGetDatabaseBuffer(PointerWrapper database);
    public static native int hsGetDatabaseBuffer2(PointerWrapper database,byte[] data, int off, int length);
    public static native void hsFreeDatabase(PointerWrapper database);
    
    public static native int hsAllocScratch(PointerWrapper database, PointerWrapper scratch);
    public static native void hsFreeScratch(PointerWrapper scratch);
    public static native int hsScan(PointerWrapper database, PointerWrapper scratch, long textBuffer, int off, int length, HitCallback callback);
    
    static {
        loadEmbeddedLibrary();
    }

    /**
     * 加载 native 库
     * 因为库比较大,没有打包到资源中, 需要另行向使用者发布库文件(native 目录下的文件)
     * @return
     */
    private static boolean loadEmbeddedLibrary() {
        String ext = getSharedExtName();
        String name = getSoName();
        StringBuilder path = new StringBuilder();
        path.append("native/")
            .append(getCurrentPlatformIdentifier())
            .append('/')
            .append(name)
            .append(".")
            .append(ext);
        String nativePath = path.toString();
        File filePath = new File(nativePath);
        if (!filePath.exists()){
            try(InputStream is = Hyperscan.class.getResourceAsStream("/"+nativePath)) {
                if (is != null){
                    filePath.getParentFile().mkdirs();
                    Files.copy(is,Paths.get(filePath.getAbsolutePath()));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            System.load(filePath.getAbsolutePath());
            return true;
        }catch(UnsatisfiedLinkError e) {
            e.printStackTrace();
            return false;
        }
    }
    static String getCurrentPlatformIdentifier() {
        
        String osName;
        if(IsWindows)
            osName = "windows";
        else if(IsLinux) {
            osName = "linux";
        } else
            osName = "darwin";
        return osName + "/" + ArchName ;
    }
    
    static String getSoName() {
        String name;
        if(IsWindows)
            name = "hyperscan";
        else if(IsLinux) {
            name = "libhs";
        } else
            name = "libhs";
        return name ;
    }
    
    static String getSharedExtName() {
        if(IsWindows)
            return "dll";
        if(IsLinux)
            return "so";
        return "dylib";
    }

}
调用:
直接使用Hyperscan.hsCompile()进行调用
加载:
JDK 提供给了我们两个方法用于载入库文件,一个是 System.load(String filename) 方法,另一个是 System.loadLibrary(String libname) 方法
两个方法都是用来装载dll文件,不论是JNI库文件还是非JNI库文件。本地方法在被调用时都需要通过这两个方法之一将其加载至内存。

System.load
System.load 参数必须为库文件的绝对路径,可以是任意路径,例如:
System.load("C:\\Documents and Settings\\TestJNI.dll"); //Windows
System.load("/usr/lib/TestJNI.so"); //Linux

System.loadLibrary
System.loadLibrary 参数为库文件名,不包含库文件的扩展名。
System.loadLibrary ("TestJNI"); //加载Windows下的TestJNI.dll本地库
System.loadLibrary ("TestJNI"); //加载Linux下的libTestJNI.so本地库
注意:TestJNI.dll 或 libTestJNI.so 必须是在JVM属性java.library.path所指向的路径中。

注意:System.loadLibrary(String libname)和java.library.path变量对应的路经相关,此方法加载的文件必须是在java.library.path这一jvm变量所指向的路径中。
可以通过如下方法来获得该变量的值:
System.getProperty("java.library.path");
默认情况下,在Windows平台下,该值包含如下位置:

1)和jre相关的一些目录
2)程序当前目录
3)系统目录(system32)
4)系统环境变量path指定目录(tomcat里面)

设置java.library.path的路径
 
1.windows 下
(1): 设置classpath的路径即可,一般的动态链接库是放到c:/window/system32这个目录下。
(2): 也可以修改环境变量,增加动态链接库的地址。
(3): 开发时设置 eclipse的动态库的地址, 具体参见:
http://blog.csdn.net/ty564457881/article/details/7066423
2.linux下
需要设置系统变量LD_LIBRARY_PATH来添加java.library.path。
因为JVM启动时,会使用系统变量LD_LIBRARY_PATH的值来初始化java.library.path属性。
java.library.path默认值
-Djava.library.path 和 LD_LIBRARY_PATH的区别
如果使用 java -Djava.library.path=/jni/library/path 的方式设置的话,会覆盖默认值。其值为:
/jni/library/path

如果使用 export LD_LIBRARY_PATH=/jni/library/path的方式设置的话,会追加其值到默认值中。LD_LIBRARY_PATH的值会插入到JRE本地库之后,操作系统库文件目录之前。其值为:
$JAVA_HOME/jre/lib/i386/server:$JAVA_HOME/jre/lib/i386
:$JAVA_HOME/jre/../lib/i386:/jni/library/path:/usr/java/packages/lib/i386:/lib:/usr/lib

猜你喜欢

转载自blog.csdn.net/zpflwy1314/article/details/100175879
今日推荐