• JNI各种环境下编译方法及初期出错分析


    转自 https://www.cnblogs.com/xyang0917/p/4172490.html

    第五步、将C/C++代码编译成本地动态库文件

          动态库文件名命名规则:lib+动态库文件名+后缀(操作系统不一样,后缀名也不一样)如:

          Mac OS X : libHelloWorld.jnilib

          Windows :HelloWorld.dll(不需要lib前缀)

          Linux/Unix:libHelloWorld.so

    1> Mac OS X

    1. gcc -dynamiclib -o /Users/yangxin/Library/Java/Extensions/libHelloWorld.jnilib jni/HelloWorld.c -framework JavaVM -I/$JAVA_HOME/include -I/$JAVA_HOME/include/darwin  

    我的$JAVA_HOME目录在:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home
    参数选项说明:

    -dynamiclib:表示编译成动态链接库

    -o:指定动态链接库编译后生成的路径及文件名

    -framework JavaVM -I:编译JNI需要用到JVM的头文件(jni.h),第一个目录是平台无关的,第二个目录是与操作系统平台相关的头文件

    2> Windows(以Windows7下VS2012为例)

    开始菜单-->所有程序-->Microsoft Visual Studio 2012-->打开VS2012 X64本机工具命令提示,用cl命令编译成dll动态库:

    1. cl -I"%JAVA_HOME%include" -I"%JAVA_HOME%includewin32" -LD HelloWorld.c -FeHelloWorld.dll   

    参数选项说明:

    -I :   和mac os x一样,包含编译JNI必要的头文件

    -LD:标识将指定的文件编译成动态链接库

    -Fe:指定编译后生成的动态链接库的路径及文件名

    3> Linux/Unix

    1. gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared HelloWorld.c -o libHelloWorld.so  

    参数说明:

    -I:          包含编译JNI必要的头文件

    -fPIC:    编译成与位置无关的独立代码

    -shared:编译成动态库

    -o:         指定编译后动态库生成的路径和文件名

    第六步、运行Java程序

           Java在调用native(本地)方法之前,需要先加载动态库。如果在未加载动态之前就调用native方法,会抛出找不到动态链接库文件的异常。如下所示:

    1. Exception in thread "main" java.lang.UnsatisfiedLinkError: com.study.jnilearn.HelloWorld.sayHello(Ljava/lang/String;)Ljava/lang/String;  
    2.     at com.study.jnilearn.HelloWorld.sayHello(Native Method)  
    3.     at com.study.jnilearn.HelloWorld.main(HelloWorld.java:9)  

    一般在类的静态(static)代码块中加载动态库最合适,因为在创建类的实例时,类会被ClassLoader先加载到虚拟机,随后立马调用类的static静态代码块。这时再去调用native方法就万无一失了。加载动态库的两种方式:

    1. System.loadLibrary("HelloWorld");  
    2. System.load("/Users/yangxin/Desktop/libHelloWorld.jnilib");  

    方式1:只需要指定动态库的名字即可,不需要加lib前缀,也不要加.so、.dll和.jnilib后缀

    方式2:指定动态库的绝对路径名,需要加上前缀和后缀

    如果使用方式1,java会去java.library.path系统属性指定的目录下查找动态库文件,如果没有找到会抛出java.lang.UnsatisfiedLinkError异常。

    1. Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld2 in java.library.path  
    2.     at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)  
    3.     at java.lang.Runtime.loadLibrary0(Runtime.java:845)  
    4.     at java.lang.System.loadLibrary(System.java:1084)  
    5.     at com.study.jnilearn.HelloWorld.<clinit>(HelloWorld.java:13)  

    大家从异常中可以看出来,他是在java.library.path中查找该名称对应的动态库,如果在mac下找libHelloWorld.jnilib文件,linux下找libHelloWorld.so文件,windows下找libHelloWorld.dll文件,可以通过调用System.getProperties("java.library.path")方法获取查找的目录列表,下面是我本机mac os x 系统下的查找目录:

    1. String libraryDirs = System.getProperties("java.library.path");  
    2. System.out.println(libraryDirs);  
    3. // 输出结果如下:  
    4. /Users/yangxin/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.  

    有两种方式可以让java从java.library.path找到动态链接库文件,聪明的你应该已经想到了。

    方式1:将动态链接库拷贝到java.library.path目录下

    方式2:给jvm添加“-Djava.library.path=动态链接库搜索目录”参数,指定系统属性java.library.path的值

    java -Djava.library.path=/Users/yangxin/Desktop

    Linux/Unix环境下可以通过设置LD_LIBRARY_PATH环境变量,指定库的搜索目录。

    费了那么大劲,终于可以运行写好的Java程序了,结果如下:

    1. yangxin-MacBook-Pro:JNILearn yangxin$ java -classpath ./bin com.study.jnilearn.HelloWorld  
    2. Java Str:yangxin  
    3. hello yangxin  

    如果没有将动态库拷贝到本地库搜索目录下,执行java命令,可通过添加系统属性java.library.path来指定动态库的目录,如下所示:

    1. yangxin-MacBook-Pro:JNILearn yangxin$ java -Djava.library.path=/Users/yangxin/Desktop -classpath ./bin com.study.jnilearn.HelloWorld  
    2. Java Str:yangxin  
    3. hello yangxin  
  • 相关阅读:
    为什么网站不被百度收录或收录清零?
    XmlSerializer序列化一组成员到文本文件
    windows phone不同页面间传值
    windows phone下进行Isolated的IO读写
    windows Phone 后退键历史的清除
    Window Phone ListBox的DataBinding:
    VGA的相关代码
    如何避免Quartus II自動將未宣告的信號視為wire?
    XINLINX约束心得
    VIM配置文件备份
  • 原文地址:https://www.cnblogs.com/dengpeng1004/p/8745917.html
Copyright © 2020-2023  润新知