Android JNI 学习(一):JNI 简介

JNI 即 Java Native Interface 是 native 编程接口,它允许在Java虚拟机(VM)内运行Java代码与其他编程语言(主要是C和C++)编写的应用程序和库进行交互操作。

JNI最重要的好处是它对底层Java VM的实现没有任何限制。因此,Java VM供应商可以添加对JNI的支持,而不会影响VM的其他部分。程序员可以编写一个native应用程序或库的版本,并期望它可以与支持JNI的所有Java VM一起使用。

本文主要将从以下几点讲述JNI相关的内容,用于我们了解JNI:

概述、背景、目标、实现方式。

一、JNI 概述

虽然您可以完全使用Java编写应用程序,但有些情况下Java本身并不能满足您的应用程序的需求。当应用程序无法完全用Java编写时,程序员使用JNI编写Java Native 方法来处理这些情况。

以下示例说明何时需要使用Java Native方法:

  • 标准Java类库不支持应用程序所需的与平台相关的功能。
  • 您已经有一个使用另一种语言编写的库,并希望通过JNI使其可以访问Java代码。
  • 您希望在较低级别的语言(如C/C++)中实现一小部分时间关键代码。

通过JNI编程,您可以使用Native方法:

  • 创建,检查和更新Java对象(包括数组和字符串)。
  • 调用Java方法。
  • 捕获并抛出异常。
  • 加载类并获取类信息。
  • 执行运行时类型检查。

二、JNI 产生的历史背景

来自不同供应商的VM提供了不同的Native方法接口。这些不同的接口迫使程序员在给定平台上生成,维护和分发多个版本的本机方法库。

我们简要介绍一些本机方法接口,例如:

  • JDK 1.0本机方法接口
  • Netscape的Java运行时接口
  • Microsoft的原始本机接口和Java / COM接口

1、JDK 1.0本机方法接口

JDK 1.0 附带了Native方法接口。不幸的是,这个接口不适合其他Java VM采用有两个主要原因。

首先,本机代码访问Java对象中的字段作为C结构的成员。但是,Java语言规没有定义对象在内存中的布局方式。如果Java VM在内存中以不同方式布局对象,则程序员必须重新编译本机方法库。

其次,JDK 1.0的本机方法接口依赖于保守的垃圾收集器。unhand例如,不受限制地使用宏使得必须保守地扫描本机堆栈。

2、Java运行时接口

Netscape提出了Java运行时接口(JRI),它是Java虚拟机中提供的服务的通用接口。JRI的设计考虑了可移植性 - 它对底层Java VM中的实现细节做了很少的假设。JRI解决了广泛的问题,包括本机方法,调试,反射,嵌入(调用)等。

3、原始本机接口和Java / COM接口

Microsoft Java VM支持两种本机方法接口。在低级别,它提供了有效的原始本机接口(RNI)。RNI提供了与JDK本机方法接口的高度源级向后兼容性,尽管它有一个主要区别。本机代码必须使用RNI函数与垃圾收集器明确交互,而不是依赖于保守的垃圾收集。

在更高级别,Microsoft的Java / COM接口为Java VM提供了与语言无关的标准二进制接口。Java代码可以像使用Java对象一样使用COM对象。Java类也可以作为COM类公开给系统的其余部分。

三、JNI 产生的目标

我们相信,统一且经过深思熟虑的标准接口为每个人提供以下好处:

  • 每个VM供应商都可以支持更多的natvie代码。
  • 工具构建器不必维护不同类型的natvie方法接口。
  • 应用程序编程人员将能够编写其natvie代码的一个版本,该版本将在不同的VM上运行。

实现标准本机方法接口的最佳方法是让所有各方都参与Java VM。因此,我们在Java许可证持有者之间组织了一系列关于统一本机方法接口设计的讨论。从讨论中可以清楚地看出,标准本机方法接口必须满足以下要求:

  • 二进制兼容性 - 主要目标是在给定平台上的所有Java VM实现中对本机方法库进行二进制兼容。程序员应该只为给定平台维护其本机方法库的一个版本。
  • 效率 - 为了支持时间关键代码,本机方法接口必须施加很少的开销。确保VM独立性(以及二进制兼容性)的所有已知技术都带有一定量的开销。我们必须以某种方式在效率和VM独立性之间达成妥协。
  • 功能 - 接口必须公开足够的Java VM内部,以允许本机方法完成有用的任务。

四、实现JNI的方式讨论

我们希望采用现有方式之一作为标准,主要是为了给在不同VM中学习多个接口的程序员带来最小的负担。但是令人失望的是,目前没有现有的解决方案来实现我们这样的想法。

Netscape的JRI是最接近我们想要的的便携式Natvie方法接口,并被用作我们设计的起点。熟悉JRI的读者会注意到API命名约定,方法和字段ID的使用,本地和全局引用的使用等方面的相似之处。尽管我们尽最大努力,但JNI与JRI不是二进制兼容的,尽管VM可以同时支持JRI和JNI。

微软的RNI是对JDK 1.0的改进,因为它解决了使用非保守垃圾收集器的本机方法的问题。但是,RNI不适合作为独立于VM的本机方法接口。与JDK一样,RNI本机方法将Java对象作为C结构访问,但也导致两个问题:

  • RNI将内部Java对象的布局暴露给本机代码。
  • 直接访问Java对象作为C结构使得无法有效地合并“写入障碍”,这在高级垃圾收集算法中是必需的。

作为二进制标准,COM确保跨不同VM的完全二进制兼容性。调用COM方法只需要间接调用,这几乎不会产生任何开销。此外,COM对象在解决版本问题方面比动态链接库有了很大的改进。

但是,使用COM作为标准Java本机方法接口受到以下几个因素的阻碍:

  • 首先,Java / COM接口缺少某些所需的功能,例如访问私有字段和引发一般异常。
  • 其次,Java / COM接口自动为Java对象提供标准的IUnknown和IDispatch COM接口,以便本机代码可以访问公共方法和字段。遗憾的是,IDispatch接口不处理重载的Java方法,并且在匹配方法名称时不区分大小写。此外,通过IDispatch接口公开的所有Java方法都被包装以执行动态类型检查和强制。这是因为IDispatch接口在设计时考虑了弱类型语言(例如Basic)。
  • 第三,COM不是处理单独的低级功能,而是旨在允许软件组件(包括完整的应用程序)协同工作。我们认为将所有Java类或低级本机方法视为软件组件是不合适的。
  • 第四,由于缺乏对UNIX平台的支持,因此立即采用COM受到阻碍。

虽然Java对象不作为COM对象公开给本机代码,但JNI接口本身与COM二进制兼容。JNI使用与COM相同的跳转表结构和调用约定。这意味着,只要跨平台支持COM,JNI就可以成为Java VM的COM接口。

JNI不被认为是给定Java VM支持的唯一本机方法接口。标准接口使程序员受益,他们希望将本机代码库加载到不同的Java VM中。在某些情况下,程序员可能必须使用较低级别的VM特定接口来实现最高效率。在其他情况下,程序员可能使用更高级别的界面来构建软件组件。实际上,随着Java环境和组件软件技术的日趋成熟,本机方法将逐渐失去意义。

五、总结

首先本文是译文,原文地址为:https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/intro.html

同时也是本人整理的JNI教程的第一篇,可能部分内容语法有点不通顺,但是看完了也能基本了解JNI是什么,产生的背景,以及JNI被实现的方式。

原文地址:https://www.cnblogs.com/renhui/p/9937541.html

时间: 2024-10-11 12:24:21

Android JNI 学习(一):JNI 简介的相关文章

android学习笔记----JNI中的c控制java

面向对象的底层实现 java作为面向对象高级语言,可对现实世界进行建模.和面向过程不同的是面向对象软件的编写不是流程的堆积,而是对业务逻辑的多视角分解和分类.其过程大致为:      1).将知识分解成不同粒度的小概念.      2).对概念进行分类,形成类.模块.系统      3).用计算机语言将其实现为对象(包含操作和数据) 然而,大多程序员编写代码时很少思考面向对象的体系是如何实现的.因为它属于底层,并不必要.但是,学习过Java反射技术并有所思考的人会意识到,面向对象的种种语法本身也

Android学习笔记--JNI的使用方法

1.JNI是什么 JNI是Java Native Interface的缩写,它提供若干的API实现Java与其他语言之间的通信.而Android Framework由基于Java语言的的Java层与基于C/C++语言的C/C++层组成,每个层中的功能模块都是以有相应的语言编写,并且两层中的大部分模块有着千丝万缕的联系.而在两层之间充当连接桥梁这一角色的就是JNI,它允许Java代码和C/C++编写的应用程序与库之间进行交互:通常在以下几种情况下使用JNI 1.注重处理速度,C/C++的处理速度要

Android学习JNI,使用JNI实现字符串加密

本节学习使用C语言加密字符串,大家都知道使用JAVA实现的加密都能够反编译的,而使用C写的加密是非常难被反编译的.所以我们使用JNI学习怎样使用C实现对字符串的加密. 首先:我们实现一个界面 布局文件就补贴出了. 其次:在MainActivity中添加一个加密和解密的本地方法 //加密本地方法 public native String encodeFromC(String text, int length); //解密本地方法 public native String decodeFromC(S

Android JNI学习笔记(四)-数据类型映射以及native调用java

1. 前言 前几篇学习了jni开发的基本流程.动态注册native函数以及相关编译文件的编写,咱们也算是知道了jni开发,但是还不够,今天咱们来学习下,java和jni的数据类型映射(说白了就是对应关系),以及如何在jni层调用java层的一些东西.偷偷告诉你们,这些全在jni.h文件里. 2. 数据类型映射 首先是我们的基本数据类型,其关系如下表描述这样. 上面关系的相关代码在jni.h的44-51行,如下 typedef unsigned char jboolean; /* unsigned

JNI学习之Invocation API

本文是对链接http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html的学习笔记,限于英文水平和对JNI的理解,可能存在错误. 简介 通过使用Invocation API,使用C/C++开发的本地应用可以访问Java虚拟机提供的特性.为了描述简单,下面提到的VM指的都是Java虚拟机. 创建VM 在本地应用里,调用JNI_CreateJavaVM()方法可以完成初始化.加载VM,并返回指向新VM对象

NDK/JNI学习--环境搭建

基于Windows来开发Android的NDK,JNI需要的环境搭建,所需要的软件如下: Android 开发环境的基本配置(SDk,ADT,Eclipse IDE,JDK) 这些都是基本的环境搭建就不细说了,参考网上文章就OK了. Apache ANT构建系统 主要是用来构建NDK编译系统的,下载地址:apache-ant-1.9.4-bin.zip,下载后解压到C:\apache-ant-1.9.4,然后配置ANT的环境变量即可. 验证安装成功: GUN make 构建系统(常用Cygwin

NDK/JNI学习--导入hello-jni工程

上一篇文章,简单搭建了NDK开发的环境,此文通过导入C:\android-ndk-r9d\samples\hello-jni(NDK自带example)来疏通真个环境. 打开Eclipse IDE,指定NDK的位置 选择的NDK位置仅对当前的Eclipse workspace有效哦.如果更改workspace,需要重新指定NDK的位置 2. 像导入普通Android工程一样导入hello-jni 此时会出现如下图错误,这个错误是Android导入工程大部分都会出现类似的(原因是开发时API Le

JNI学习心得(1)

最近由于公司需求,开发Android项目,之前没接触过,了解甚少. Android驱动层的开发流程(个人理解):(自上而下)Android APP =>JNI => HAL => Linux devices Read/Write 据我了解,大致流程就是这样,如有不对,欢迎大礼拍砖. 由于驱动层一般由C/C++开发.需要与JAVA交互需要通过JNI. JNI负责JAVA与其他语言(C/C++)进行交互.类似于windows平台下,不同语言之间用.dll封装,进行交互. JNI最终会生成 .

ndk学习17: jni之Java调用C&C++

一.Hello World 1. 定义函数原型 native关键字定义的函数即为jni函数 2.生成头文件 切换到src目录执行: (这个过程可以写脚本自动完成,比如自动拷贝到jni目录) javah -jni 包名.类名 在根目录下生成: org_bing_testjni_MainActivity.h 3. 工程中添加jni代码 工程右键->添加native code->输入名字->finish 多了如下文 新建一个Application.mk,配置相关选项(详细查看ndk有关Appl

ndk学习18: JNI之C&C++调用Java

一.Java反射机制 先了解Java反射机制原理 例子网上很多,反射很灵活 二. 在JNI层调Java 用途: Java层逆向比较容易,增加逆向门槛,把调用都写到JNI层,  让Java层无调用关系 注意: C和C++有所不同,这里使用C++作为例子 1. 首先在代码中提供一个ShowLog函数 private void ShowMsg() { Log.d("_BING_", "ShowMsg"); } 2. 在上次的Add例子加入代码 JNIEXPORT jint