`

jni 使用 【转载】

阅读更多

  JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。  JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

 
JNI在Windows上的使用
  • 运行环境


    CPU : AMD Moblie Athlon 64 3200+
    Mem : 1024 MB

    OS : Windows xp sp2
    JDK : java version "1.5.0_06"
    IDE : Eclipse 3.1.2  、  Microsoft Visual Studio 2005


  • 编写JAVA 代码

    //JNITest.java

    /**
     * @author chunyv
     *
     */
    public class JNITest {

     /**
      * @param args
      */
     
     static
     {
       try
       {
          System.loadLibrary("JNITest");
       }
       catch(Exception e)
       {
           System.out.println("load library failure!");
       }
     }
     
     public native static void version();
     
     public native static void setint(int i);
     public native static int getint();
     
     public native static void setstr(String str);
     public native static String getstr();
     
     public native static void setgbk(byte[] gbkstr);
     public native static byte[] getgbk();
     
     public static void main(String[] args) {
      // TODO Auto-generated method stub
      String test = "Hello World!";
      String test2 = "你好!\n\t\t--chunyv";
      System.out.println("Proc Start");
      byte[] end = {0};

      try
      {
       byte[] mybytedb = test2.getBytes("gbk");
       byte[] mybyte = new byte[mybytedb.length + end.length];
       System.arraycopy(mybytedb , 0 , mybyte , 0 ,mybytedb.length);
       System.arraycopy(end , 0 , mybyte , mybytedb.length , end.length);
       
       
       JNITest jnitest = new JNITest();
       
       jnitest.setint(6);
       System.out.println("setint ok");
       System.out.println("get int form library :"+jnitest.getint());
       System.out.println("getint ok");
       
       jnitest.setstr(test);   
       System.out.println("setstr ok");
       
       System.out.println(jnitest.getstr());
       System.out.println("getstr ok");
       
       jnitest.setgbk(mybyte);
       System.out.println("setgbk ok");
       
       System.out.println(jnitest.getgbk());
       System.out.println("getgbk ok");
       
       jnitest.version();
      }
      catch(Exception e)
      {
       e.printStackTrace();
      }
     }

    }


  • 生成 .h 文件


    javac JNITest.java
    javah JNITest


  • 实现 JNITest.h 中的方法

    /*
    * author chunyv
    * JNITest dll
    */

    #include "JNITest.h"
    #include <windows.h>


    JNIEXPORT void JNICALL Java_JNITest_version
      (JNIEnv *, jclass)
    {
     printf("JNI Test\n\t\t--chunyv");
    }


    JNIEXPORT void JNICALL Java_JNITest_setint
      (JNIEnv *, jclass, jint ii)
    {
     i = ii;
    }


    JNIEXPORT jint JNICALL Java_JNITest_getint
      (JNIEnv *, jclass)
    {
     return i;
    }
     

    JNIEXPORT void JNICALL Java_JNITest_setstr
      (JNIEnv * env, jclass, jstring jstr)

     jboolean test = true;

     memset(str , 0 , sizeof(str));

     sprintf_s(str ,env->GetStringUTFChars(jstr,&test));

     env->ReleaseStringUTFChars(jstr , NULL);
    }

    JNIEXPORT jstring JNICALL Java_JNITest_getstr
      (JNIEnv * env, jclass)

     return WindowsTojstring(env , str);
    }

    JNIEXPORT void JNICALL Java_JNITest_setgbk
      (JNIEnv * env, jclass, jbyteArray myjbyte)
    {
     memset(strgbk , 0 , sizeof(strgbk));

     sprintf_s(strgbk ,(char *)env->GetByteArrayElements(myjbyte,0));
    }

    JNIEXPORT jstring JNICALL Java_JNITest_getgbk
      (JNIEnv * env, jclass)

     return WindowsTojstring(env , strgbk);
    }

    jstring WindowsTojstring( JNIEnv* env, char* str_tmp )
    {
        jstring rtn = 0;
        int slen = (int)strlen(str_tmp);
        unsigned short * buffer = 0;
       
     if( slen == 0 )
     {
            rtn = env->NewStringUTF(str_tmp );
     }
        else
        {
            int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str_tmp, slen, NULL, 0 );

            buffer = (unsigned short *)malloc( length*2 + 1 );
           
      if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str_tmp, slen, (LPWSTR)buffer, length ) >0 )
      {
                rtn = env->NewString(  (jchar*)buffer, length );
      }
        }

        if( buffer )
     {
            free( buffer );
     }

        return rtn;
    }


  • 将生成的JNITest.dll 放到 .class 所在的目录 测试 JAVA <wbr>JNI <wbr>的应用


    java JNITest

    Proc Start
    setint ok
    get int form library :6
    getint ok
    setstr ok
    Hello World!
    getstr ok
    setgbk ok
    你好!
                    --chunyv
    getgbk ok
    JNI Test
                    --chunyv


JNI 在 FreeBSD 上的应用 

  • 运行环境

    CPU : Intel(R) Pentium(R) 4 CPU 2.40GHz (2393.94-MHz 686-class CPU)
    Mem : 512 MB

    OS : FreeBSD 6.2-PRERELEASE
    JDK : java version "1.5.0"
    IDE : vim + gcc 3.4.4

  • java代码同上
  • 生成 .h 文件同上
  • 实现 JNITest.h 中的方法

    /*
    * author chunyv
    * JNITest so
    * add "int  FreeBSD2Jstring(char * src ,
    *  char * dst,
    *  int * len);" into JNITest.h
    */

    #include <stdio.h>
    #include <iconv.h>
    #include <stdlib.h>
    #include <string.h>
    #include "JNITest.h"

    int i = 0;
    char str[1024];
    char strgbk[1024];

    JNIEXPORT void JNICALL Java_JNITest_version
      (JNIEnv *env, jclass jc)
    {
     printf("JNI Test\n\t\t--chunyv\n");
    }


    JNIEXPORT void JNICALL Java_JNITest_setint
      (JNIEnv * env, jclass jc, jint ii)
    {
     i = ii;
    }


    JNIEXPORT jint JNICALL Java_JNITest_getint
      (JNIEnv * env, jclass jc)
    {
     return i;
    }
     

    JNIEXPORT void JNICALL Java_JNITest_setstr
      (JNIEnv * env, jclass jc, jstring jstr)

     jboolean test = 1;

     memset(str , 0 , sizeof(str));

     sprintf(str ,(*env)->GetStringUTFChars(env ,jstr,&test));

     (*env)->ReleaseStringUTFChars(env ,jstr , NULL);
    }

    JNIEXPORT jstring JNICALL Java_JNITest_getstr
      (JNIEnv * env, jclass jc)

     return (*env)->NewStringUTF(env ,str);
    }

    JNIEXPORT void JNICALL Java_JNITest_setgbk
      (JNIEnv * env, jclass jc, jbyteArray myjbyte)
    {
     memset(strgbk , 0 , sizeof(strgbk));

     sprintf(strgbk ,(char *)(*env)->GetByteArrayElements(env ,myjbyte,0));
    }

    JNIEXPORT jstring JNICALL Java_JNITest_getgbk
      (JNIEnv * env, jclass jc)

     char test[1024] ;
     sprintf(test ,strgbk);
     int len = (int ) strlen(strgbk);
     
     if( FreeBSD2Jstring(test , strgbk ,&len ))
     {
      printf("convert error\n");
      return NULL;
     }
     
     return (*env)->NewStringUTF(env ,strgbk);
    }

    int  FreeBSD2Jstring(char * src ,
      char * dst,
      int * len)
    {
     size_t n_in = strlen(src);
     size_t n_out = *len+2;
     
     memset(dst , 0 , n_out);
      
     iconv_t test = iconv_open("UTF-8","GBK");
     if(test == (iconv_t)-1)
     {
      printf("iconv open error\n");
      return -1;
     }
     
     if((size_t)-1 == iconv(test ,(const char **) & src ,&n_in , & dst , &n_out))
     {
      printf("iconv convert error\n");
      return -1;
     }
     
     if(test)
     {
      iconv_close(test);
     }

     *len = n_out;

     return 0;
    }


  • 编译 .c 文件,将生成的库文件放到.class 所在目录并测试 .class

    编译库文件
    gcc -Wall -fPIC -shared -o libJNITest.so -I /usr/local/diablo-jdk1.5.0/include/ -I /usr/local/diablo-jdk1.5.0/include/freebsd/ -I /usr/local/include/ -liconv -L /usr/local/lib/ JNITest.c

    测试 .class
    java -Djava.library.path=./ JNITest

  • 测试结果

    Proc Start
    setint ok
    get int form library :6
    getint ok
    setstr ok
    Hello World!
    getstr ok
    setgbk ok
    你好!
                    --chunyv
    getgbk ok
    JNI Test
                    --chunyv

 

JNI在Linux上的使用请参阅 《JNI在FreeBSD上的使用》部分

注:实例仅供参考,转载请注明出处,欢迎交流学习,谢谢!!

分享到:
评论

相关推荐

    JNA—JNI终结者(转载)

    **标题:“JNA—JNI终结者”** 这篇文章探讨的主题是Java Native Access (JNA) 和 Java Native Interface (JNI),两者都是Java平台上的技术,用于在Java应用程序中调用本地(非Java)代码。它们允许Java程序员与...

    JNI完全技术手册 带完整书签

    Chap9:如何编写jni方法(转载)... 55 1、实例一:在jni中调用标准c中自带的函数printf(): 57 2、实例二、调用c 语言用户定义的函数... 58 3、实例三、在jni函数中访问java类中的对象实例域... 58 4、实例四:在...

    JNI文档资料源码_2020_01_22

    【Android NDK 开发】Visual Studio 2019 使用 CMake 开发 JNI 动态库 ( 动态库编译配置 | JNI 头文件导入 | JNI 方法命名规范 ) 博客地址 : https://hanshuliang.blog.csdn.net/article/details/104068609 博客...

    JNI学习示例代码,含java代码工程和win32 dll工程

    JNI,全称为Java Native ...版权声明:本文为CSDN博主「clever101」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/clever101/article/details/125938242

    JNI调用大全

    Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息......Chap 4:用javah产生一个...Chap5:使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能... 47 Chap9:如何编写jni方法(转载)... 55

    android jni开发实例

    转载几篇介绍android jni开发方法的文章,有介绍基础的,有介绍方法的,也有实例可参考。

    JNI文档资料源码_2020_02_04.zip

    版权声明:本文为CSDN博主「韩曙亮」的原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://hanshuliang.blog.csdn.net/article/details/104108556

    JAVA NATIVE

    《JAVA NATIVE VC Com 的转载连载文章》这篇文章主要探讨了如何在Java中使用Native接口与VC++编译的DLL进行交互,以及DLL的基本概念和创建方法。以下是对这些知识点的详细说明: 1. **DLL (Dynamic Link Library)**...

    网站一些关于学习的网站

    网站通常会有一套完整的版权保护机制,包括版权声明、侵权举报流程、快速删除机制等,以维护创作者的合法权益,同时也提醒用户要尊重版权,合法使用网络资源。 #### 四、专业资源的获取与利用 部分内容还提到了...

    jdbc连接数据库的方式2

    三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧,这些技巧能够使我们更好地发挥系统的性能和实现更多的功能(系转载)。  1、在客户端软件开发中使用Thin驱动程序  在开发Java软件方面,Oracle...

    jna-3.5.2jar

    经典的JNI的基础之上的一个框架。 JNA项目地址:https://jna.dev.java.net/ JNA使Java调用原生函数就像.NET上的P/Invoke一样方便、快捷。 JNA的功能和P/Invoke类似,但编写方法与P/Invoke截然不同。JNA没有使用...

    尼斯知识体系:不积跬步无以至千里,每天进步一点点,激情,自我调节,爱与分享

    知识体系总结 如果你感到委屈,证明你还有底线;如果你感到迷茫,证明你还有追求;如果你感到痛苦,证明你还有力气;...NDK JNI学习 文章标题 状态 原创,转载 已发布 原创 已发布 原创 自定义视图 文章标题 状态 原创

    android 调用微信扫一扫(调用微信.so实现)

    对于.so文件,需要根据项目支持的CPU架构,将它们放入对应的`jniLibs`目录下,如`jniLibs/armeabi`、`jniLibs/armeabi-v7a`等。 接下来,注册应用。在微信开放平台上创建应用并获取AppID,然后在AndroidManifest....

    JAVA调用C语言写的SO文件

    因为工作需要写一份SO文件,作为手机硬件IC读卡和APK交互的桥梁,也是中间件,看了网上有说到JNI接口技术实现,这里转载了一个实例 1 // 用JNI实现 2 // 实例: 3 4 // 创建HelloWorld.java 5 class HelloWorld...

    android NDK 开发总结

    3. NDK带来的益处:NDK可以让C或C++语言开发者快速加入Android平台的应用开发,同时也能让Java开发者通过JNI(Java Native Interface)更加方便地调用底层操作和处理性能敏感的任务。 4. 开发环境的部署:文档中...

Global site tag (gtag.js) - Google Analytics