JNI语言基本知识
作者:动力节点 发布时间:2022-01-20 20:02:46
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语言基本知识网站的支持!
来源:http://blog.sina.com.cn/s/blog_9c6852670102wxgs.html


猜你喜欢
- 1.为什么要使用synchronized在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。关键字syn
- 网站中为了防止恶意获取验证短信、验证邮箱,都会在点击获取验证码的按钮上做个倒计时的效果,如何实现这个效果,具体内容如下效果图: 代
- 从左到右 A B C 柱 大盘子在下, 小盘子在上, 借助B柱将所有盘子从A柱移动到C柱, 期间只有一个原则: 大盘
- 本文记录了笔者的第一个Java程序,基于Java抽象窗口工具(abstract window toolkit , AWT)和Swing(Sw
- 今天工作中遇到一个需求,就是获取 excel 里面的内容,并且把 excel 另存为 csv,因为本人以前未接触过,所以下面整理出来的代码均
- 前言最近在网上看到一篇文章,里面说到:List<T>.FindAll的效率竟然比for循环还差,下面是文章的截图:我在上文代码基
- [LeetCode] 159. Longest Substring with At Most Two Distinct Characters
- 本文实例为大家分享了Android实现页面短信验证功能的具体代码,供大家参考,具体内容如下目标效果:上一篇博文介绍的是使用SDK中自带的验证
- import java.io.BufferedInputStream;import java.util.ArrayList;import j
- 基础部分内容差不多讲解完了,今天开始进入Java提高篇部分,这部分内容会比之前的内容复杂很多,希望大家做好心理准备,看不懂的部分可以多看两遍
- 介绍前面的内容对Handler做了介绍,也讲解了如何使用handler,但是我们并不知道他的实现原理。本文从源码的角度来分析如何实现的。首先
- 本文实例讲述了C#中Socket通信用法。分享给大家供大家参考。具体如下:一、UDP方式:服务器端代码:static void Main(s
- Junit这种老技术,现在又拿出来说,不为别的,某种程度上来说,更是为了要说明它在项目中的重要性。 凭本人的感觉和经验来说,在项目中完全按标
- Android中实现定时器的四种方式第一种方式利用Timer和TimerTask1、继承关系java.util.Timer基本方法sched
- 本文实例讲述了C#获取USB事件API。分享给大家供大家参考。具体如下:const int WM_DEVICECHANGE = 0x2190
- Maven可以使用mvn package指令对项目进行打包,如果使用java -jar xxx.jar执行运行jar文件,会出现"
- 简介Microsoft官网关于 WindowChome 的介绍截取Microsoft文章的一段话:若要在保留其标准功能时自定义窗口,可以使用
- 问题描述在应用MyBatis时,使用对象关系映射,将对象和Aliase映射起来。在Mybatis的文档明确写出,如果你没有明确定义实体类的A
- spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问
- Android独有的安全机制,除了权限机制外,另外一个就是签名机制了。签名机制主要用在以下两个主要场合起到其作用:升级App和权限检查。升级