java基础知识之-本地方法

java语言较之C/C++语言,其带来的优势显而易见,但实际中,有时还是会需要编写或使用其他
语言的代码,这 种代码通常成为本地代码。在java中使用本地代码应用的并不多,使用本地代码的
情形一般有三种:

  1. 在该种语言中,已经有了大量测试过的和调试过的代码,且功能成熟稳定,这时候,若将这些代码移植到java语言就会显得很费时。

  2. java代码通常占内存比较大,有时会降低系统性能,而像 C/C++ 它们的运行效率会高的多,当代码的执行速度至关重要的时候,可以考虑使用本地代码。

  3. 如果当前应用程序需要访问系统的各个特性和设备时。使用了本地代码,应用将丧失可移植性,通常不会去使用本地方法。

一、用java调用C函数

如果要用java调用 C 中的一个函数,那么应遵循如下步骤:

第一步, 将该函数封装在一个类中

即在这个类中声明该本地方法,需关键字 native ,它会提醒编译器,该方法将在外部定义,如下所示;

   class NativeMethod {  
       public static native void greeting();//本地方法可以是静态的也可以是非静态的;
    }

第二步,编写相应的 C 函数,

在这里需要注意,必须按照java运行环境预期的那样来命名这个函数,如果类中含有非ASCII的
字母或数字,需用相应的十六进制替换,其实这个工作是繁琐的,而正如我们所预期的,JDK中
提供了一个相应的命令来完成这项工作,可以使用 javah 命名来帮我们自动生成函数名,如下所示:

    javac NativeMethod.java
    javah NativeMethod

随后它会产生相应的 C 头文件,NativeMethod.h

第三步,将函数原型写到源文件中,如下所示:

include "NativeMethod.h"
include <stdio.h>
JNIEXPORT void JNICALL Java_NativeMethod_greeting(JNIEnv* env, jclass cl){  
       printf("Hello World!\n");
    }

第四步,将本地的 C 代码编译到一个动态装载库中,此步操作依赖于编译器。

最后一步,
在定义本地方法的java类中添加一个对System.loadLibrary方法的调用,如:

   static{  
       System.loadLibrary("NativeMethod");//一般书写在静态方法块中
    }

随后就可以在main方法中测试了。

二、数值参数与返回值

  1. 在C与java编程语言之间传递参数时,由于这两种语言对数字类型的实现不同,所以需要指定他们彼此之间的对应类型,数据类型之间的对应关系如下
    int->jint,long->jlong,byte->jbyte,char->jchar,short->jshort,float
    ->jfloat,double->jdouble,boolean->jboolean
  2. 对于字符串参数,需要考虑编程语言之间的编码方式,java中的字符串是UTF-16编码点的序列,而C的字符串则是以null结尾的字节序列。java本地接口有两组操作字符串的函数,一组是把java字符串转换成改良的UTF-8字节序列,另一组将它们转换成UTF-16数值的数组,也就是转换成jchar数组。从C代码访问java字符串常

用的方法有如下几种:

    jstring NewStringUTF(JNIEnv* env,const char bytes[])
    //根据改良的UTF-8字节序列,返回一个新的java字符串,当字符串无法构造时,返回null

    jsize getStringUTFLength(JNIEnv* env,jstring string)
    //返回进行UTF-8编码所需的字节数

    const ibyte* GetStringUTFChars(JNIEnv* env,jstring string,jboolean* isCopy)
    //返回改良UTF-8编码的字符串的指针,直到ReleaseStringUTFChars函数调用前该指针一直有效的。 

    void ReleaseStringUTFChars(JNIEnv* env,jstring string,const ibyte bytes[])
    //通知虚拟机本地代码不再需要通过bytes访问Java字符串

    void GetStringRegion(JNIEnv * env,jstring string,jsize start,jsize length,jchar *buffer)
    //将一个Unicode字符序列从字符串复制到用户提供的缓存中。

     void GetStringUTFREdion(JNIEnv * env,jstring string,jsize start,jsize length,jchar *buffer)
    //将一个改良的UTF-8字符序列从字符串复制到用户提供的缓存中。

更多方法可查看API文档

3、C调用java一般遵循三个步骤:

  1. 获取隐式参数的类
  2. 获取方法ID
  3. 进行调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值