java jni 原理_JNI的实现原理

JNI接口函数和指针

Java虚拟机访问本机代码通过调用JNI的功能特性。JNI的功能都可以通过一个接口指针。一个接口指针是一个指向指针的指针。这个指针指向一个一个指针数组,这个数组中的每一个成员指向一个函数入口。每个接口的功能是在一个预定义的内部数组的偏移量。

164830e103c087ce44018b9f0e0f931c.png

图一、JNI接口函数和指针

JNI接口的组织像C++虚函数列表或COM接口一样。使用接口列表的好处是JNI名字空间与本地代码分离开来。

JNI接口指针只在当前线程有效。因此,一个本地方法不能从一个线程通过该接口指针指向另一个线程。

本地方法像参数一样接收JNI接口指针。当在同一个线程中有多个调用本地方法,VM保证相同的接口指针传递到这个本地方法。然而,本地方法可以被不同的Java线程调用,因此可能会收到不同的JNI接口指针。

加载和链接本机方法

本地方法装载的是System.loadLibrary方法。在下面的例子中,类的初始化方法加载一个特定平台的本地库中的本地方法f定义如下:

package

pkg;

class

Cls {

native

double f(int i, String s);

static

{

System.loadLibrary(“pkg_Cls”);

}

}

System.loadLibrary中的参数是一个库名,它是由程序员任意选择的。该系统遵循一个标准:把库名转换为本地库名的方法,但这是与平台相关的。例如,Solaris系统把pkg_Cls转换为libpkg_Cls.so,而Win32系统则转换为pkg_Cls.dll。

程序员可以使用一个单一的库来存储所有的任何类需要的本地方法,只要这些类能够被同一类加载器加载。虚拟机内部会为每个类加载器维护一个加载本地库的的列表。

虚拟机会检查与本地库匹配的方法名。虚拟机会首先查找短名称,即没有参数的名称签名。然后,再查找长名称,即带参数签名的名称。程序员只有当一个本地方法与另一本机方法重载时才需要使用长名称。

在下面的例子中,本地方法g不必须连接使用长名称,因为其另一个方法g不是一个本地方法,因此也没有在本地库。

class

Cls1 {

int

g(int i);

native

int g(double d);

}

本机方法的参数

JNI接口指针是本地方法的第一个参数。在JNI接口指针的类型是JNIEnv。第二个参数不同,这取决于本地方法是静态的还是非静态的。第二个参数为一个非静态本地方法时是对对象的引用。第二个参数为静态本地方法是对的Java类的引用。

其余的参数对应于常规的Java方法的参数。本机方法通过返回值调用传递它的结果返回到调用例程。

下面代码举例说明了使用C函数来实现f本地方法时,本地方法f声明如下:

package

pkg;

class

Cls {

native

double f(int i, String s);

...

}

Java对象引用

像整数,字符,等等这些原始类型,都在Java与本机代码之间复制。另外,任意Java对象,是通过引用传递。虚拟机必须跟踪所有已传递到本地代码的对象,使这些对象不会被垃圾收集器释放。相反,本地代码必须有一种机制来通知虚拟机什么时候不再需要使用这些对象了。此外,垃圾收集器必须能够搬运对象所指的本机代码。

全局和局部引用

JNI把本地代码使用的相关对象分为两在范畴:局部和全局引用。局部引用的有效期为一个本地方法调用的时间,并自动机方法返回后获释。全球引用仍然有效,直到它们被明确释放。

所有的Java的JNI函数返回的对象都是局部引用。JNI允许程序员通过局部引用来创建全局引用。

局部引用只有在线程中被建立时才有效,并只在该线程中有效。本地代码不能在线程之间调用局部引用。

访问字段和方法

JNI允许本地代码访问字段和调用Java对象的方法。JNI通过符号名称和类型签名来判定方法和字段。例如,要调用类cls中的方法f,本地代码首先获得一个方法的ID,如下:

jmethodID

mid = env->GetMethodID(cls, “f”, “(ILjava/lang/String;)D”);

本地代码便可以重复的使用method

ID而在方法查找时不需要时间,具体如下:

jdouble

result = env->CallDoubleMethod(obj, mid, 10, str);

报告程序错误

JNI不检查编程错误,如空指针或非法参数类型传递。非法使用的参数类型包括用父类对象引用子类对象。

Java异常

JNI允许本地方法任意提高Java异常。本机代码也可以处理严重的Java异常。Java的未处理的异常是传送回了VM。

因此,程序员可以快速检查上次的JNI调用的返回值,以确定是否发生了错误,并调用一个函数,ExceptionOccurred(),以获得异常对象,它包含一个错误的条件更详细的说明。

异常处理

在本地代码中有两种方法处理异常:

1、本机方法可以选择立即返回,在Java代码中抛出异常,启动了本地方法调用。

2、本地代码能过调用ExceptionClear()来清除异常,然后执行自己的异常处理代码。

在异常被提升之后,本地代码在其它JNI调用之前必须先清除异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jQuery ajax读取本地json文件_jQuery请求本地JSON文件,在谷歌浏览器运行时报跨域错误_Vscode使用Live Server

json文件 {"first":[{"name":"张三","sex":"男"},{"name":"李四","sex":"男"},{"name":"王武","sex":"男"},{"name":"李…

Vue打包并发布项目

一、 打包vue项目步骤: 1、对当前vue项目进行打包的命令如下: npm run build2、打包完成,会输出Build complete并且在vue项目中会生成一个名字为dist的打包文件。如下图: 二、 使用静态服务器工具包发布打包的vue项目 1、首先…

Grammarly:最优秀的日常英文写作辅助工具——论文英文校验

使用Grammarly也有一些心得,在此分享给大家。 1,Grammarly是什么? Grammarly是一款在线语法纠正和校对工具,支持Windows、Mac、iOS和Android等多个平台。它能够检查单词拼写、纠正标点符号、修正语法错误、调整语气以及给出风格…

SpringMVC @RequestBody和@ResponseBody原理解析

SpringMVC RequestBody和ResponseBody原理解析 前言 RequestBody作用是将http请求解析为对应的对象。例如: http请求的参数(application/json格式): {"accountId": 10,"adGroupId": "12345678",…

java 高性能缓存_高性能Java缓存----Caffeine

简单介绍Caffeine是新出现的一个高性能的Java缓存,有了它完全可以代替Guava Cache,来实现更加高效的缓存;Caffeine采用了W-TinyLFU回收策略,集合了LRU和LFU的优点,提供了一个最佳的命中率,在效率上可以秒杀…

@ResponseBody 转化成json后与实体类字段名不一致_SpringMVC字符串解析成json对象(@RequestBody注解和@ResponseBody注解)

ResponseBody 转化成json后与实体类字段名不一致 实体类A字段名由B改成C后,Controller 中返回的List中字段名仍然是C 经过ResponseBody返回到前台后又变成了B 后来发现公司项目采用的是阿里的fastjson, 是开源的Json格式化工具库 此工具库是根据实体类…

java togglebutton_ToggleButton和Switch使用大全

本文转载自:Android零基础入门第21节:ToggleButton和Switch使用大全http://www.apkbus.com/blog-205190-68463.html(出处: 安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户),转载应备注出处,尊重原创上期学习了CheckB…

MyBatis之工作原理,简单实体的增加、修改、删除、查询_Mybatis-原理总结

一、MyBatis之工作原理 MyBatis是一个半自动映射框架。所谓半自动,是相对Hibernate全表映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系。 我们知道,JDBC有四个核心对象: (1)DriverManager&#…

MySQL优化:如何避免回表查询?_什么是索引覆盖?

数据库表结构: create table user (id int primary key,name varchar(20),sex varchar(5),index(name) )engineinnodb;select id,name where nameshenjianselect id,name,sex where nameshenjian多查询了一个属性,为何检索过程完全不同? 什…

mysql提示Column count doesn‘t match value count at row 1错误

我们在对数据库进行添加信息时可能会遇到如下错误: Column count doesn’t match value count at row 1 该错误的意思是传入表的字段数和values值的个数不一样 我总结了一下,主要有3个易错点: 1.要传入表中的字段数和values后面的值的个数不…

java 阅发布模式_redis发布订阅模式

一 前言虽然有消息队列,我们还是要了解一下redis发布订阅模式哟!!!!!二发布订阅模式PUBLISH 命令向通道发送信息,此客户端称为publisher 发布者;SUBSCRIBE 向命令通道订阅信息&#…

把实体 转为json 数据格式---jackson 的详细用法_Jackson快速入门

首先介绍三个注解: JsonAutoDetect (method/field):作用于方法或字段,用来表明,当生成json的时候忽略有该annotation的方法或字段 JsonIgnore 过滤不需要转成json的属性 JsonIgnoreProperties 主要用于过滤掉一些不需要的属性 以上三个注…

java 类的加载顺序_Java 中类的加载顺序

这其实是去年校招时我遇到的一道阿里巴巴的笔试题(承认有点久远了-。-),嗯,如果我没记错的话,当时是作为Java方向的一道选做大题。当然题意没有这么直白,题目只要求你写出程序运行后所有System.out.println的输出结果,…

Jackson转换json大写_关于jackson转化json的原理_jackson序列化和反序列化Json

背景 web工程中,数据交互是不可避免的,相比xml,json是现在流行的数据交互。 在调试接口中,发现返回字段的大小写不是我所期望的,原本应该返回的nNum字段变成了nnum,这样就导致和前端约定的有出入了。 ja…

svn利用TortoiseSVN忽略文件或文件夹(目录)

忽略已经版本控制的文件 如果你不小心添加了一些应该被忽略的文件,你如何将它们从版本控制中去除而不会丢失它们?或许你有自己的IDE配置文件,不是项目的一部分,但将会花费很多时间使之按照自己的方式工作。 如果你还没有提交&am…

SpringMVC 参数绑定详解

概述 记得之前跟前端同事联调接口的时候,后端SpringMVC需要接收数组类型的参数,然后跟前端说需要传数组类型过来。后来前端童鞋传了数组,但是后端接收不成功,联调失败。那时候由于时间关系没有仔细研究这块,当时想了个…

java 连接远程服务器_java实现连接远程服务器并执行命令的基本原理

一、所需jar包需要借助Ganymed SSH的jar包: ganymed-ssh2-build210.jar二、实现原理Ganymed SSH-2 java在整个访问过程中担当SSH的客户端,由于Linux系统自带SSH服务,所以可以直接访问Linux系统并执行相关命令,而 Windows系统则需要首先安装S…

SpringMVC接收基本类型和包装类型

先看一个示例: 注意这两个参数都没有加RequestParam注解。 测试: 直接报错。即没有加RequestParam注解,基本数据类型参数是必填的。 再测试: 直接返回null,也就是说包装类型参数,没有加RequestParam注解&…

SpringMVC 【参数绑定详讲、默认支持参数类型、自定义参数绑定、RequestParam 注解】

SpringMVC 第四篇【参数绑定详讲、默认支持参数类型、自定义参数绑定、RequestParam 注解】 参数绑定 我们在 Controller 使用方法参数接收值,就是把 web 端的值给接收到 Controller 中处理,这个过程就叫做参数绑定… 默认支持的参数类型 从上面的用…

MySQL中 IS NULL、IS NOT NULL、不等于, 能用上索引吗?

MySQL的WHERE子句中包含 IS NULL、IS NOT NULL、! 这些条件时便不能使用索引查询,只能使用全表扫描。 告诉大家结论: MySQL中决定使不使用某个索引执行查询的依据就是成本够不够小,如果null值很多,还是会用到索引的。 自己做了个…