Java关键字之native详解

目录
  • 1、JNI:Java Native Interface
  • 2、用C语言编写程序本地方法
    • 一、编写带有native声明的方法的java类
    • 二、使用javac命令编译所编写的java类,生成.class文件
    • 三、使用javah -jni java类名生成扩展名为 h 的头文件
    • 四、使用C语言实现本地方法
  • 3、JNI调用C的流程图
  • 4、native关键字
  • 总结

本篇博客我们将介绍Java中的一个关键字——native。

native 关键字在 JDK 源码中很多类中都有,在 Object.java类中,其 getClass() 方法、hashCode()方法、clone() 方法等等都是用 native 关键字修饰的。

public final native Class<?> getClass();
public native int hashCode();
protected native Object clone() throws CloneNotSupportedException;

那么为什么要用 native 来修饰方法,这样做有什么用?

1、JNI:Java Native Interface

在介绍 native 之前,我们先了解什么是 JNI。

一般情况下,我们完全可以使用 Java 语言编写程序,但某些情况下,Java 可能会不满足应用程序的需求,或者是不能更好的满足需求,比如:

  • ①、标准的 Java 类库不支持应用程序平台所需的平台相关功能。
  • ②、我们已经用另一种语言编写了一个类库,如何用Java代码调用?
  • ③、某些运行次数特别多的方法代码,为了加快性能,我们需要用更接近硬件的语言(比如汇编)编写。

上面这三种需求,其实说到底就是如何用 Java 代码调用不同语言编写的代码。那么 JNI 应运而生了。

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

通过 JNI,我们就可以通过 Java 程序(代码)调用到操作系统相关的技术实现的库函数,从而与其他技术和系统交互,使用其他技术实现的系统的功能;同时其他技术和系统也可以通过 JNI 提供的相应原生接口开调用 Java 应用系统内部实现的功能。

在windows系统上,一般可执行的应用程序都是基于 native 的PE结构,windows上的 JVM也是基于native结构实现的。Java应用体系都是构建于 JVM 之上。  

可能有人会问,Java不是跨平台的吗?如果用 JNI,那么程序不就将失去跨平台的优点?确实是这样的。

JNI 的缺点:

①、程序不再跨平台。要想跨平台,必须在不同的系统环境下重新编译本地语言部分。

②、程序不再是绝对安全的,本地代码的不当使用可能导致整个程序崩溃。一个通用规则是,你应该让本地方法集中在少数几个类当中。这样就降低了JAVA和C之间的耦合性。

目前来讲使用 JNI 的缺点相对于优点还是可以接受的,可能后面随着 Java 的技术发展,我们不在需要 JNI,但是目前 JDK 还是一直提供对 JNI 标准的支持。

2、用C语言编写程序本地方法

上面讲解了什么是 JNI,那么我们接下来就写个例子,如何用 Java 代码调用本地的 C 程序。

官方文档如下:https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html

步骤如下:

①、编写带有 native 声明的方法的java类,生成.java文件;(注意这里出现了 native 声明的方法关键字)

②、使用 javac 命令编译所编写的java类,生成.class文件;

③、使用 javah -jni java类名 生成扩展名为 h 的头文件,也即生成.h文件;

④、使用C/C++(或者其他编程想语言)实现本地方法,创建.h文件的实现,也就是创建.cpp文件实现.h文件中的方法;

⑤、将C/C++编写的文件生成动态连接库,生成dll文件;

下面我们通过一个 HelloWorld 程序的调用来完成这几个步骤。

注意:下面所有操作都是在所有操作都是在目录:D:\JNI 下进行的。

一、编写带有native声明的方法的java类

public class HelloJNI {
    //native 关键字告诉 JVM 调用的是该方法在外部定义
    private native void helloJNI();

    static{
        System.loadLibrary("helloJNI");//载入本地库
    }
    public static void main(String[] args) {
        HelloJNI jni = new HelloJNI();
        jni.helloJNI();
    }

}

用 native 声明的方法表示告知 JVM 调用,该方法在外部定义,也就是我们会用 C 语言去实现。

System.loadLibrary("helloJNI");加载动态库,参数 helloJNI 是动态库的名字。我们可以这样理解:程序中的方法helloJNI() 在程序中没有实现,但是我们下面要调用这个方法,怎么办呢?我们就需要对这个方法进行初始化,所以用 static 代码块进行初始化。

这时候如果我们直接运行该程序,会报“A Java Exception has occurred”错误:  

二、使用javac命令编译所编写的java类,生成.class文件

  

执行上述命令后,生成 HelloJNI.class 文件:

三、使用javah -jni java类名生成扩展名为 h 的头文件

执行上述命令后,在 D:/JNI 目录下多出了个 HelloJNI.h 文件:

四、使用C语言实现本地方法

如果不想安装visual studio的,我们需要在 windows平台安装 gcc。

注意安装版本的选择,根据系统是32位还是64位来选择。64位点击下载

安装完成之后注意配置环境变量,在 cmd 中输入 g++ -v,如果出现如下信息,则安装配置完成:  

接着输入如下命令:

gcc -m64  -Wl,--add-stdcall-alias -I"C:\Program Files\Java\jdk1.8.0_152\include" -I"C:\Program Files\Java\jdk1.8.0_152\include\include\win32" -shared -o helloJNI.dll helloJNI.c

-m64表示生成dll库是64位的。后面的路径表示本机安装的JDK路径。生成之后多了一个helloJNI.dll 文件

最后运行 HelloJNI:输出 Hello JNI! 大功告成。  

3、JNI调用C的流程图

4、native关键字

通过上面介绍了那么多JNI的知识,终于到介绍本篇文章的主角——native 关键字了。相信大家看完上面的介绍,应该也是知道什么是 native 了吧。

native 用来修饰方法,用 native 声明的方法表示告知 JVM 调用,该方法在外部定义,我们可以用任何语言去实现它。简单地讲,一个native Method就是一个 Java 调用非 Java 代码的接口。

native 语法:

①、修饰方法的位置必须在返回类型之前,和其余的方法控制符前后关系不受限制。

②、不能用 abstract 修饰,也没有方法体,也没有左右大括号。

③、返回值可以是任意类型

我们在日常编程中看到native修饰的方法,只需要知道这个方法的作用是什么,至于别的就不用管了,操作系统会给我们实现。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 全面了解Java中Native关键字的作用

    初次遇见 native是在 java.lang.Object 源码中的一个hashCode方法: public native int hashCode(); 为什么有个native呢?这是我所要学习的地方.所以下面想要总结下native. 一.认识 native 即 JNI,Java Native Interface 凡是一种语言,都希望是纯.比如解决某一个方案都喜欢就单单这个语言来写即可.Java平台有个用户和本地C代码进行互操作的API,称为Java Native Interface (Ja

  • 详解Java中native关键字

    一. 什么是Native Method    简单地讲,一个Native Method就是一个java调用非java代码的接口.一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C.这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数.    "A native method is a Java method whose implementatio

  • Java中的Native关键字讲解

    目录 一.Java中Native关键字的语法 二.Native关键字是如何工作的? 三.代码示例 四.Java中Native关键字的优势 五.规则 六.总结 前言: native关键字充当JAVA语言与除JAVA之外的其他语言编写的代码块或库之间的链接,这可能取决于您操作的机器.如果将native关键字应用于一个方法,那么这意味着该方法将通过JNI(JAVA native interface)使用其他语言(如C或C++)编写的本机代码来实现. 一.Java中Native关键字的语法 本机代码的语

  • Java Native关键字原理及作用解析

    初次遇见 native是在 java.lang.Object 源码中的一个hashCode方法: public native int hashCode(); 为什么有个native呢?这是我所要学习的地方.所以下面想要总结下native. 一.认识 native 即 JNI,Java Native Interface 凡是一种语言,都希望是纯.比如解决某一个方案都喜欢就单单这个语言来写即可.Java平台有个用户和本地C代码进行互操作的API,称为Java Native Interface (Ja

  • Java关键字之native详解

    目录 1.JNI:Java Native Interface 2.用C语言编写程序本地方法 一.编写带有native声明的方法的java类 二.使用javac命令编译所编写的java类,生成.class文件 三.使用javah -jni java类名生成扩展名为 h 的头文件 四.使用C语言实现本地方法 3.JNI调用C的流程图 4.native关键字 总结 本篇博客我们将介绍Java中的一个关键字——native. native 关键字在 JDK 源码中很多类中都有,在 Object.java

  • JAVA关键字及作用详解

    Java关键字及其作用 一. 总览: 访问控制 private protected public 类,方法和变量修饰符 abstract class extends final implements interface native new static strictfp synchronized transient volatile 程序控制 break continue return do while if else for instanceof switch case default 异常

  • Java关键字之instanceof详解

    目录 1.obj 必须为引用类型,不能是基本类型 2.obj 为 null 3.obj 为 class 类的实例对象 4.obj 为 class 接口的实现类 5.obj 为 class 类的直接或间接子类 6.问题 7.深究原理 8.instanceof 的实现策略 instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为: boolean result = obj instanceof Class 其中 obj 为一个对象,Class 表示一个类

  • java之assert关键字用法案例详解

    Java2在1.4中新增了一个关键字:assert.在程序开发过程中使用它创建一个断言(assertion).,它的语法形式有如下所示的两种形式: 1.assert condition; 这里condition是一个必须为真(true)的表达式.如果表达式的结果为true,那么断言为真,并且无任何行动 如果表达式为false,则断言失败,则会抛出一个AssertionError对象.这个AssertionError继承于Error对象, 而Error继承于Throwable,Error是和Exc

  • java方法及this关键字原理分析详解

    目录 步骤1 .给顾客增加一个吃饭的方法 步骤 2 . 没有加static的属性和方法,一定需要先new对象 步骤 3 . 用new出来的对象去执行eat方法 步骤 4 . 怎么理解c.eat() 步骤 5 . 消息接受器 步骤 6 . 如果有两个顾客? 步骤 7 . 答案 步骤 8 .其实有个this 步骤 9 . 在eat方法里面直接使用this 步骤 10 . 构造方法 步骤 11 . 总结:this的意义是什么? 步骤 12 . 道理我都懂,那static又是什么? 步骤 13 . 本节

  • Java super关键字的用法详解

    目录 super关键字的三种用法: 1. super.成员变量 2. super.成员方法 3. super():调用父类中的构造方法 3.1.1 隐式调用父类无参数构造方法super() 3.1.2 显式调用父类有参数构造方法super(id) super关键字作用:在子类内部调用父类对象 基础语法: 1.在类的继承中,当子类继承了父类, 在构造子类的时候,一定要先帮助父类进行构造: 2. 调用super()必须写在子类构造方法的第一行,以保证在执行任何动作前,对象已经完成了初始化,否则编译不

  • Java this关键字的使用详解

    目录 1. 先看一段代码,并分析问题 2. 深入理解 this 3. this 的注意事项和使用细节 4. this 的案例 1. 先看一段代码,并分析问题 public class This01 { //编写一个main方法 public static void main(String[] args) { Dog dog1 = new Dog("大壮", 3); //dog1调用了 info()方法 dog1.info(); } } class Dog{ //类 String nam

  • Java this关键字的引用详解

    目录 为什么要有this引用? 什么是this引用 this引用的特性 为什么要有this引用? 我们先看一段代码示例 public class Date { public int year; public int month; public int day; public void setDay(int y,int m,int d){ year = y; month = m; day = d; } public void printDate(){ System.out.println(year

  • Java super关键字的使用详解

    目录 1.super介绍 2.super的基本使用 3.子类和父类方法的调用细节 4.super和this的区别 1.super介绍 我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类. 用于访问父类的属性,方法,构造器 2.super的基本使用 我们来演示以下子类调用父类的属性,方法和构造器 父类: /** * super关键字演示父类 */ public class SuperFather { public int n1 = 100; int n2 = 110; pr

  • Java中this和super关键字的使用详解

    目录 父类空间优先于子类对象产生 super和this的含义 super和this的用法 继承的特点 父类空间优先于子类对象产生 在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身.目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员.代码体现在子类的构造方法调用时,一定先调用父类的构造方法.理解图解如下: super和this的含义 super :代表父类的存储空间标识(可以理解为父亲的引用). this :代

随机推荐