• 浅试 JNI编程


    好吧,开始我的第一个JNI试验小程序

    HelloWorld.java 代码清单

     1 public class HelloWorld {
     2 
     3     static {
     4         System.loadLibrary("HelloWorld");
     5     }
     6 
     7     public static native void hello(String msg);
     8 
     9 
    10     public static void main(String args[]){
    11         HelloWorld hw = new HelloWorld();
    12         hw.Display();
    13     }
    14 
    15     void Display(){
    16         System.out.println("hello,world");
    17     }
    18 
    19 }

     记得文件名必须和类名一致,编译

      javac HelloWorld

    利用 javah 命令生成c 的头文件,命令形式 javah  <packagename>.<classname>,因为我没有定义包名,所以直接是类名:

      javah HelloWorld

    这样在目录下将会生成以包名为文件名的头文件 HelloWorld.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class HelloWorld */
    
    #ifndef _Included_HelloWorld
    #define _Included_HelloWorld
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     HelloWorld
     * Method:    hello
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_HelloWorld_hello
      (JNIEnv *, jclass, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    下面我们需要建立HeloWorld的动态共享库,先创建一个HelloWorld.c, 然后将头文件中的函数定义拷贝过来,并且指定参数的变量名

    #include "HelloWorld.h"
    
    JNIEXPORT void JNICALL Java_HelloWorld_hello(JNIEnv * env, jclass jz, jstring s)
    {
    }

    这是个毫无用处的函数,在java程序中我们也只有声明,没有调用,现在我只是试验他是否能正常装载。用 gcc 命令进行编译:

      gcc -I/usr/lib/jdk1.6.0_45/include -I/usr/lib/jdk1.6.0_45/include/linux -fPIC  -c HelloWorld.c

    gcc的 -I 选项指定头文件的搜索路径,jni.h 在jdk 的include子目录里,而jni_md.h在 include/linux下,所以要把这两个路径加入头文件的搜索路径。-c 选项指定生成 .o 文件,如果缺少 -c 选项gcc会自动链接生成可执行文件,因为在我们的程序中缺少 main 函数,所以会出现错误。另外我们希望生成的是动态链接库,所以我们不需要生成可执行文件,只要生成目标文件即可。经过执行上面的命令,在目录下会生成 HelloWorld.o

    我们执行下面的命令生成动态链接库

    gcc -shared -o libHelloWorld.so HelloWorld.o

    -shared 指示生成共享库, 而 -o 可以指定生成的共享库的文件名,注意linux下共享库的命名是有讲究的,首先文件名必须由lib作为前缀,其次扩展名为.so, 而他们之间的名字应该和 System.loadLibrary调用指定的名字相符,而且大小写一致。

    回头看看我们java文件中的代码片段:

    public class HelloWorld {
    
        static {
            System.loadLibrary("HelloWorld"); // 会寻找 libHelloWorld.so 动态库
        }
    
        ...
    
    }

    下一步使用java 命令运行我们的java程序:

      java HelloWorld

    会报告错误:

    Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)
        at java.lang.Runtime.loadLibrary0(Runtime.java:823)
        at java.lang.System.loadLibrary(System.java:1028)
        at HelloWorld.<clinit>(HelloWorld.java:6)
    Could not find the main class: HelloWorld.  Program will exit.

    这是因为java找不到我们的动态库。我们很奇怪的是明明动态库就在当前的目录下,而且文件的命名也符合标准,为何还找不到。这里的原因是java程序并非足够的智能,根据错误的提示可以知道我们可以通过设置 java.library.path 变量来指定库的搜索路径,好这样一来,问题就简单了,运行下面的命令,搞定:

      java -Djava.library.path=. HelloWorld

    通过将java.libray.path=. 来将java.libray.path设置为当前目录。

  • 相关阅读:
    创业公司必备的5款团队协作工具
    测试人必备:国内外最好用的6款Bug跟踪管理系统
    BUG克星:几款优秀的BUG跟踪管理软件
    千亿级SaaS市场:企业级服务的必争之地
    如何使用iClap创建普通批注
    详析手游圈从业人员必须知道的行业术语
    企业级服务元年:iClap高效解决手游更新迭代问题
    手游精品时代,iClap参会TFC高效解决手游问题
    全新办公方式,iClap引领企业级服务新浪潮
    vue自学小demo----前端
  • 原文地址:https://www.cnblogs.com/zengsiyu/p/4780263.html
Copyright © 2020-2023  润新知