• linux下JNI开发步骤详解


    前期准备:

    1、Java JDK

    2、gcc

    3、g++

    注意:gcc和g++的版本号要一致:如下:

    [juan@juan~]$ gcc --version  
    gcc (GCC) <span style="color: #ff0000;" > 4.6 . 3   20120306  (Red Hat  4.6 . 3 - 2 )</span>  
    Copyright (C) 2011  Free Software Foundation, Inc.  
    This is free software; see the source for copying conditions.  There is NO  
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
      
    [qiaoning@qiaoning ~]$ g++ --version  
    bash: g++: command not found...  
    [qiaoning@qiaoning ~]$ gcc --version  
    gcc (GCC) <span style="color: #ff0000;" > 4.6 . 3   20120306  (Red Hat  4.6 . 3 - 2 )</span>  
    Copyright (C) 2011  Free Software Foundation, Inc.  
    This is free software; see the source for copying conditions.  There is NO  
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

    linux(Fedora) 安装gcc yum install gcc 安装g++ yum install gcc-c++

    确保上述准备工作完成后开始下边的工作:

    Java代码:

    public   class  Hello {  
        static  {  
            try  {  
                System.loadLibrary("hello" );              
            } catch  (UnsatisfiedLinkError e) {  
                e.printStackTrace();  
            }  
        }  
          
        public  Hello() {};  
          
        public   native   void  SayHello(String strName);  
    }  

    在终端输入 javac Hello.java 后生成Hello.class 文件

    然后:javah Hello 生成 Hello.h文件

     

    然后在相同的目录下新建一个Hello.cpp文件:内容如下:

    Cpp代码
    #include "Hello.h"   
    #include <stdio.h>   
    // 与 Hello.h 中函数声明相同   
    JNIEXPORT void  JNICALL Java_Hello_SayHello  (JNIEnv * env, jobject arg, jstring instring)  
    {  
      // 从 instring 字符串取得指向字符串 UTF 编码的指针   
      const  jbyte *str =  
        (const  jbyte *)env->GetStringUTFChars( instring, JNI_FALSE );  
      printf("Hello,%s\n" ,str);  
      // 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。   
      env->ReleaseStringUTFChars( instring, (const   char  *)str );  
      return ;  
    }  
    接下来编译生成共享库:
    gcc -I/usr/lib/jvm/java- 1.6 . 0 -openjdk- 1.6 . 0.0 /include -I/usr/lib/jvm/java- 1.6 . 0 -openjdk- 1.6 . 0.0 /include/linux -fPIC -c Hello.cpp  

     

    注意:这儿可能产生的错误:

    gcc: error trying to exec  'cc1plus' : execvp: No such file or directory 

    原因:没有安装g++,或者gcc和g++的版本不一致

     

    /usr/lib/jvm/java- 1.6 . 0 -openjdk- 1.6 . 0.0  根据自己机器实际的目录做相应的调整 

    编译成功后生成Hello.o

    gcc -shared -Wl,-soname,libhello.so. 1  -o libhello.so. 1.0  Hello.o 
    gcc -shared  
    -Wl,-soname,libhello.so.1 -o libhello.so.1.0 Hello.o 

    此命令生成生成 libhello.so.1.0

    接下来将生成的共享库拷贝为标准文件名

    cp libhello.so. 1.0  libhello.so  

    最后通知动态链接程序此共享文件的路径。

    export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH  

    接下来将生成的共享库拷贝为标准文件名

    cp libhello.so.1.0 libhello.so

    最后通知动态链接程序此共享文件的路径。

    export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH 

     

    最后是java测试代码:

    public   class  ToSay   
     {   
         public   static   void  main(String argv[])   
         {   
             ToSay say = new  ToSay();   
         }   
         public  ToSay()   
         {   
             Hello h = new  Hello();   
             // 调用本地方法向 John 问好   
             h.SayHello("John" );              
         }   
     }   

    用 javac 编译 ToSay.java,生成 ToSay.class 
    向执行普通 Java 程序一样使用 java ToSay,我们会看到在屏幕上出现 Hello,John。 


    应用中注意事项:

    1 . 如果可以通过 TCP/IP 实现 Java 代码与本地 C/C++ 代码的交互工作,那么最好不使用以上提到的 JNI 的方式,因为一次 JNI 调用非常耗时,大概要花 0.5 ~ 1 个毫秒。

    2 . 在一个 Applet 应用中,不要使用 JNI。因为在 applet 中可能引发安全异常。

    3 . 将所有本地方法都封装在单个类中,这个类调用单个 DLL。对于每种目标操作系统,都可以用特定于适当平台的版本替换这个 DLL。这样就可以将本地代码的影响减至最小,并有助于将以后所需的移植问题包含在内。

    4 . 本地方法要简单。尽量将生成的 DLL 对任何第三方运行时 DLL 的依赖减到最小。使本地方法尽量独立,以将加载 DLL 和应用程序所需的开销减到最小。如果必须要运行时 DLL,则应随应用程序一起提供它们。

    5 . 本地代码运行时,没有有效地防数组越界错误、错误指针引用带来的间接错误等。所以必须保证保证本地代码的稳定性,因为,丝毫的错误都可能导致 Java 虚拟机崩溃。

     

  • 相关阅读:
    1、一条sql查询语句的执行过程
    go 内存分配
    GO Json
    gorm CRUD:读写数据
    go 基于切片的队列实现
    go的错误处理
    grpc
    sqlalchemy 判断字段是否存在
    定时函数
    用Python获取Linux资源信息的三种方法
  • 原文地址:https://www.cnblogs.com/snake-hand/p/2517412.html
Copyright © 2020-2023  润新知