JNI语言基本知识

 更新时间:2017年10月18日 10:22:00   作者:动力节点  
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。接下来通过本文给大家分享jni 基础知识,感兴趣的朋友一起看看吧

JNI简介

JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。

一、本地方法的参数

如何本地方法声明为static,那么生成的头文件中的本地方法形式如下:

JNIEXPORT void JNICALL Java_com_tao_test_NativeTest_sayHello (JNIEnv * , jclass);

这两个参数的意思是什么:JNIEnv类型实际上代表了Java环境。通过这个JNIEnv*指针,就可以对Java端的代码进行操作。例如,创建Java类的对象,调用Java对象的方法,获取Java对象的属性等等。JNIEnv的指针会被JNI传入到本地方法的实现函数中来对Java端的代码进行操作。而jclass,则代表调用这个静态方法类的Class对象,即该Class类的字节码。

如何本地方法没有声明为static,那么生成的头文件中的本地方法形式如下:

JNIEXPORT void JNICALL Java_com_tao_test_NativeTest_sayHello (JNIEnv * , jobject);

jobject类型相当于java中的Object类型,它代表调用这个本地方法的对象,实际上准确的说,,保持了一个对  调用这个方法的的对象的引用。比如说,如果是new NativeTest().sayHello()调用这个方法,那么这个引用指向了这个new NativeTest()对象。

JNIEnv类中有许多函数可以用:

NewObject   创建一个对象

NewString  创建一个String对象

New<TYPE>Array  创建某个类型的数组

Get/Set<TYPE>Field   获取或设置某个成员变量的属性 

Get/SetStatic<TYPE>Field  获取或设置某个成静态员变量的属性

Call<TYPE>Method/CallStatic<TYPE>Method   调用某个java对象的方法/或静态方法

等等许多函数

二、数值参数

用Java代码调用C\C++代码时候,肯定会有数值的传递。两者属于不同的编程语言,在数据类型上有很多差别,应该要知道他们彼此之间的对应类型。例如,尽管C拥有int和long的数据类型,但是他们的实现却是取决于平台的。在一些平台上,int类型是16位的,而在另外一些平台上市32位的整数。基于这个原因,Java本地接口定义了jint,jlong等等。

Java类型和C/C++数据类型的对应关系,可以看到,这些新定义的类型名称和Java类型名称具有一致性,只是在前面加了个j,如int对应jint,long对应jlong。

我们看看jni.h和jni_md.h头文件,可以更直观的了解:

typedef unsigned char  jboolean; 
typedef unsigned short jchar; 
typedef short      jshort; 
typedef float      jfloat; 
typedef double     jdouble; 
typedef long jint; 
typedef __int64 jlong; 
typedef signed char jbyte; 

可以看到,例如jint代表的是和Java类型int一样的类型,但是并不是C/C++中int。从定义可以看到,Java中的int,也就是jni中的jint,对应的是C/C++中的long类型。

所以如果要在本地方法中要定义一个jint类型的数据,规范的写法应该是 jint i=10L;

在 比如jchar代表的是Java类型的char类型,实际上在C/C++中却是unsigned short类型 ,而在C/C++中有这样的定义:typedef unsigned short wchar_t。所以jchar就是相当于C/C++中的宽字符,也就是说java中的char  相当于C/C++中的宽字符。所以如果要在本地方法中要定义一个jchar类型的数据,规范的写法应该是jchar c=L'C';

实际上,所以带j的类型,都是代表Java中的类型,它与C/C++中的类型是不一样的,所以在内部都要转换,我们在使用的时候也需要小心。可以看后面关于JNI中对字符串的操作。

三。Java对象在C\C++代码中的形式

查看jni.h头文件,可以看到下面的内容

class _jclass : public _jobject {}; 
class _jthrowable : public _jobject {}; 
class _jstring : public _jobject {}; 
class _jarray : public _jobject {}; 
class _jbooleanArray : public _jarray {}; 
class _jbyteArray : public _jarray {}; 
class _jcharArray : public _jarray {}; 
class _jshortArray : public _jarray {}; 
class _jintArray : public _jarray {}; 
class _jlongArray : public _jarray {}; 
class _jfloatArray : public _jarray {}; 
class _jdoubleArray : public _jarray {}; 
class _jobjectArray : public _jarray {}; 

其实这些加了_j首字母的类,都是集成于_jobject,这也是为了照顾我们java中的,Object类是一切类的基类。

这些类,对应的就是java中的类,只不过,在C/C++中换了中形式而已。

四、jclass类和如何取得jclass对象

在Java中,Class类型代表一个类编译的字节码,即这个类,里面包含了这个类的所有信息。在JNI中,同样定义了这样一个类,那就是jclass。了解反射的人都知道Class类是如何重要,可以通过反射获得java类的信息和访问里面的方法和成员变量。所以在JNI中,也有这样一个jclass类,来代表Class类。
JNIEnv有几个方法可以取得jclass对象:

jclass FindClass(const char *name) {
    return functions->FindClass(this, name);
 }

FindClass会在系统classpath下寻找类,传入完整的类型,注意包的间隔使用   / ,而不是.   比如:

jclass cls_string=env->FindClass("java/lang/String");
jclass GetObjectClass(jobject obj) {
    return functions->GetObjectClass(this,obj);
  }
jclass GetSuperclass(jclass sub) {
    return functions->GetSuperclass(this, sub);
  }

得到java类的Class对象,即jclass,那么就可以用和反射差不多的形式,来得到java类中的成员变量和方法等等,虽然方式和Class不一样,不过大抵的形式相当。

总结

以上所述是小编给大家介绍的JNI语言基本知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • java利用CountDownLatch实现并行计算

    java利用CountDownLatch实现并行计算

    这篇文章主要介绍了java利用CountDownLatch实现并行计算,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • 详解Java的继承

    详解Java的继承

    大家好,本篇文章主要讲的是详解Java的继承,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • Mybatis的几种传参方式详解

    Mybatis的几种传参方式详解

    这篇文章主要介绍了Mybatis的几种传参方式详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • SpringBoot中使用Cookie实现记住登录的示例代码

    SpringBoot中使用Cookie实现记住登录的示例代码

    这篇文章主要介绍了SpringBoot中使用Cookie实现记住登录的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Java中常用的五种List声明并赋值操作方式

    Java中常用的五种List声明并赋值操作方式

    在Java编程中经常会使用到集合类来存储和操作多个元素,List是一种常见的集合类,它允许存储重复的元素,并且保持元素的插入顺序,这篇文章主要给大家介绍了关于Java中常用的五种List声明并赋值操作的相关资料,需要的朋友可以参考下
    2024-02-02
  • 详解Java高级特性之反射

    详解Java高级特性之反射

    这篇文章主要介绍了Java高级特性之反射的相关知识,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 详解java 单例模式及方法总结

    详解java 单例模式及方法总结

    这篇文章主要介绍了详解java 单例模式及方法总结的相关资料,需要的朋友可以参考下
    2017-05-05
  • 全面解析@InsertProvider执行原理

    全面解析@InsertProvider执行原理

    这篇文章主要介绍了全面解析@InsertProvider执行原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • JDBC下Idea添加mysql-jar包的详细过程

    JDBC下Idea添加mysql-jar包的详细过程

    这篇文章主要介绍了JDBC下Idea添加mysql-jar包的详细过程,添加jar包首先到官网下载jar包,然后idea导入jar包,在就是检查,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11
  • 确保SpringBoot定时任务只执行一次的常见方法小结

    确保SpringBoot定时任务只执行一次的常见方法小结

    在Spring Boot项目中,确保定时任务只执行一次是一个常见的需求,这种需求可以通过多种方式来实现,以下是一些常见的方法,它们各具特点,可以根据项目的实际需求来选择最合适的方法,需要的朋友可以参考下
    2024-10-10

最新评论