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上的使用》部分

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值