Java中native方法和JNI基础

合集下载

Native 方法

Native 方法

Native 方法Native 方法是在Java程序中与底层操作系统交互的一种方式。

它是使用本地库(Native Library)提供的函数来执行特定的操作。

与Java代码相比,Native方法可以直接调用底层操作系统的功能,因此可以提高程序的性能和效率。

在Java中,使用关键字`native`声明一个方法为Native方法。

Native方法的具体实现通常是通过调用编写的本地库来完成的,本地库是编译成特定平台的机器码的动态链接库。

在运行时,Java虚拟机(JVM)会加载本地库并执行其中的函数。

与普通的Java方法不同,Native方法不能直接在Java代码中实现具体功能,它只是作为一个接口,实际的功能由本地库提供。

在Java代码中调用Native方法时,JVM会将其转换为底层平台所支持的本地函数调用。

Native方法的使用场景主要涉及到需要与操作系统底层进行交互的情况,例如操作文件、网络通信、调用硬件设备等。

通过使用Native方法,可以更加高效地执行这些底层操作。

然而,使用Native方法也存在一些潜在的问题。

首先,由于涉及操作系统底层,不同平台的实现方式可能不同,因此需要针对不同平台编写相应的本地库。

同时,本地库的编写需要使用特定的编程语言(如C或C++),这对于Java开发者来说可能需要一定的学习成本。

另外,使用Native方法还可能带来安全隐患。

由于Native方法可以直接访问底层资源,如果没有进行适当的安全措施,可能会导致内存泄漏、缓冲区溢出等问题。

因此,在使用Native方法时,需要慎重考虑其必要性,并且遵循相关的使用原则和安全规范。

java的native方法

java的native方法

在Java中,native方法是指那些在Java虚拟机(JVM)上由本地代码实现的方法。

这些方法通常是在Java程序运行时,通过Java Native Interface(JNI)与本地代码进行交互。

使用native方法的主要原因是为了利用已经存在的高性能本地代码,或者为了与特定的操作系统或硬件接口进行交互。

例如,某些系统级操作可能需要直接访问底层硬件或操作系统,而Java本身可能无法提供这样的功能。

要声明一个native方法,你需要在Java类中添加native关键字。

例如:
java
public class NativeDemo {
public native void nativeMethod();
}
然后,你需要使用javah工具生成一个C头文件,该文件包含Java方法的C签名。

这个头文件可以用于在本地代码中实现该方法。

最后,你需要编写本地代码来实现该方法。

这通常是在C或C++中完成的。

然后,你需要使用JNI将本地代码与Java程序连接起来。

需要注意的是,使用native方法可能会带来一些复杂性,例如错误处理、内存管理等问题。

因此,在使用native方法时,需要谨慎考虑其潜在的风险和影响。

java native方法调用原理

java native方法调用原理

java native方法调用原理Java的Native方法允许在Java代码中调用本地(即非Java虚拟机)中实现的方法。

它们通常用于与操作系统、硬件或C/C++库进行交互。

Native方法调用原理如下:1. 编写本地方法:使用Java的native关键字在Java类中定义一个本地方法,并将其声明为native。

例如:native void myNativeMethod();2. 编译Java类文件:使用javac命令编译Java类文件,生成对应的.class文件。

3. 生成本地方法库:使用javah命令生成一个包含本地方法的C头文件。

例如:javah MyClass,将生成一个名为MyClass.h 的头文件。

4. 实现本地方法:在生成的头文件中实现native方法的具体功能。

例如,在C/C++中实现myNativeMethod()方法。

5. 编译本地方法库:使用C/C++的编译工具将之前实现的本地方法库编译为可执行的库文件。

例如,在Windows上使用GCC编译器编译为.dll文件,在Linux上使用GCC编译器编译为.so文件。

6. 加载本地方法库:在Java代码中使用System.loadLibrary()方法加载已编译的本地方法库。

例如:System.loadLibrary("mylib"),其中mylib是库文件的名称。

7. 调用本地方法:在Java代码中通过调用本地方法来调用实现的本地功能。

例如:myNativeMethod()。

在运行时,Java虚拟机会在调用本地方法时,将该方法的控制权传递给本地方法库,由库文件中对应的方法实现来执行。

执行完成后,Java虚拟机将控制权返回给Java代码继续执行。

需要注意的是,Native方法存在一定的开销,并且对Java的跨平台性有一定影响。

因此,在使用Native方法时,应该谨慎选择并进行性能测试。

native方法

native方法

native方法Native方法是指在Java程序中调用本地(Native)方法,即由其他语言编写的方法。

在Java中,我们可以使用关键字native来声明一个方法,表明该方法的实现是由其他语言编写的。

在实际应用中,我们通常会使用Native方法来调用一些底层的系统函数或者与硬件相关的操作,以提高程序的性能和扩展Java的应用范围。

首先,我们需要了解Native方法的使用场景。

在一些特定的应用中,我们可能需要直接与操作系统或者底层硬件进行交互,而这些操作可能无法通过纯Java代码来实现。

这时,我们就可以使用Native方法来调用C、C++等语言编写的函数,以实现对底层系统资源的访问和操作。

比如,在图形处理、音视频处理、网络编程等领域,Native方法都有着广泛的应用。

其次,我们需要了解Native方法的使用方式。

在Java中,我们可以使用关键字native来声明一个Native方法,但是在实际使用中,我们需要通过Java Native Interface(JNI)来实现Java与其他语言的交互。

JNI是Java提供的一套机制,用于实现Java与其他语言的通信,它提供了一组API,使得Java程序可以调用本地方法,并且本地方法也可以调用Java程序中的方法和访问Java对象。

接着,我们需要了解Native方法的实现步骤。

首先,我们需要在Java中声明Native方法,并且使用关键字native进行修饰。

然后,我们需要使用javah命令生成对应的头文件,这个头文件包含了Native方法的声明。

接下来,我们需要使用C、C++等语言编写对应的本地方法,并且将其编译成动态链接库(DLL)。

最后,我们需要在Java程序中加载对应的动态链接库,并且通过JNI调用Native方法。

此外,我们还需要了解Native方法的优缺点。

Native方法的优点在于可以实现对底层系统资源的直接访问和操作,以及提高程序的性能和扩展Java的应用范围。

java从入门到精通学习笔记-Lesson3(native方法)

java从入门到精通学习笔记-Lesson3(native方法)

native方法●Sun公司提供的JNI是Java平台的一个功能强大的接口。

这个JNI接口提供了Java与操作系统本地代码互相调用的功能。

●Native方法是用户在Java中可以使用,但不能编写的方法。

●JNI(Java Native Interface Java本地接口),它允许Java虚拟机(JVM)内部运行的Java代码能够与用其它编程语言(如C、C++、汇编语言)编写的应用程序和库进行互操作。

●JNI最大的好处是它没有对底层Java虚拟机的实现施加任何限制,因此,Java虚拟机厂商可以在不影响虚拟机其它部分的情况下添加对JNI的支持。

程序员只需编写一种版本的本地(Native)应用程序和库,就能够与所有支持JNI 的Java虚拟机协同工作。

●JNI可以理解为Java和本地应用程序之间的中介。

那么我们什么时候使用JNI呢?如果我们想要访问操作系统的特有功能,想要同特殊的硬件设备沟通,我们可以使用JNI技术,利用其它语言去实现、去调用、去访问操作系统的特有功能。

如果我们想重复使用过去编写的非java语言编写的代码,我们也可以使用JNI 技术。

如果我们想实现实时性很强的代码,可以采用其它语言去实现,如C和汇编语言,然后用JNI技术在Java中调用这种实现。

用本地方法编写一个Java程序(以HelloW orld.java为例):一、写Java代码:class HelloWorld {public native void displayHelloWorld();static {System.loadLibrary("hello");}public static void main(S tring[] args) {new HelloWorld().displayHelloWorld();}}二、编译Java代码:javac HelloWorld.java三、创建. h 的文件javah -jni HelloWorld产生的HelloWorld.h文件如下:/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloWorld */#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif/** Class: HelloWorld* Method: displayHelloWorld* Signature: ()V*/JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif四、写一个本地方法的实现新建HelloWorldImp.c#include <jni.h>#include "HelloWorld.h"#include <stdio.h>JNIEXPORT void JNICALLJava_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)//HelloWorld.h中声明的函数原型{printf("Hello world!\n");return;}第五步:创建一个共享的库cl -I C:\Java\j2sdk1.5.0\include-I C:\Java\j2sdk1.5.0\include\win32 -LD HelloWorldImp.c -Fehello.dll这里的cl是安装了Visual C++而提供的编译工具。

java jni方法

java jni方法

java jni方法(最新版2篇)篇1 目录1.java jni方法的概念及作用2.java jni方法的工作原理3.java jni方法的优缺点4.java jni方法的应用场景篇1正文一、java jni方法的概念及作用Java Native Interface(JNI)是一种用于在Java程序中调用本地(C/C++)代码的技术。

通过JNI,Java程序可以与底层系统进行交互,实现更高效、更底层的系统级操作。

JNI提供了一组API,使得Java程序可以调用本地代码,并且能够将Java对象传递给本地代码,反之亦然。

二、java jni方法的工作原理JNI的工作原理主要包括以下几个步骤:1.加载本地库:Java程序通过System.loadLibrary()或静态初始化块等方式加载本地库。

2.获取本地函数:Java程序通过JNIEnv对象的GetStaticMethodID()方法获取本地函数的ID。

3.创建本地对象:Java程序通过JNIEnv对象的NewXXXX()方法创建本地对象。

4.调用本地函数:Java程序通过JNIEnv对象的CallXXXX()方法调用本地函数,并将参数传递给本地函数。

5.回收本地对象:Java程序在不再需要使用本地对象时,通过JNIEnv对象的DeleteXXXX()方法释放内存。

三、java jni方法的优缺点1.优点:* 实现了Java程序与底层系统的交互,可以更高效、更底层地实现系统级操作。

* 可以调用C/C++代码,提高了开发效率和质量。

2.缺点:* 开发难度较大,需要对C/C++语言有一定的了解。

* 由于涉及到内存管理等问题,容易造成内存泄漏和安全问题。

* 由于需要将Java对象转换为本地对象,效率较低。

四、java jni方法的应用场景JNI适用于以下场景:1.需要使用底层系统资源或API进行系统级操作,如音频、视频、图形处理等。

2.需要高效地调用C/C++代码,提高开发效率和性能。

JNI详解

JNI详解

JNI详解javanativeinterface,(jni)是一个标准的javaapi,它支持将java代码与使用其他编程语言编写的代码相集成。

在这里主要就是java和c++的交互。

1:java调用c++:首先,对java文件中要调用的方法进行本地声明,关键字为native。

它只需要宣布,而不是实施。

像publicnativevoidloginsuccessnative(stringp_qqid);publicnativestaticvoidsetstat enative(inti);然后我们需要在C++文件中实现这些方法。

这些方法有特定的格式。

我们可以使用javah命令来帮助生成这些方法的声明,调用javac来编译我们的Java类,得到类文件,然后javahyourclassname可以得到一个H文档:#include#ifdef_cplusplus}#endif#endif事实上,只要我们知道这种格式,我们也可以手动编写。

因为Java直接在CPP中查找方法,所以H文件,我们也不需要声明。

最后我们需要将c++文件,编译成so然后加入java工程,并在java中导入。

静态{system.loadlibrary(“test”);}//系统将自行判断后缀。

2:在c++中调用java方法。

在C++中调用java是比较麻烦的,因为我们需要在C++中获得java的运行环境,并找到我们想要使用的类和方法。

首先,我们需要理解几个概念:javavm:这个代表java的虚拟机。

所有的工作都是从获取虚拟机的接口开始的,如何获取这个接口呢?我们之前导入c的组件时调用了:system.loadlibrary(“test”);调用此方法时,Java将调用组件first_Onload()函数的JNI,该函数用于两个目的:一是:告诉javavm此c组件使用那一个jni版本。

如果你没有提供jni_onload()函数,vm会默认使用最老的jni1.1版本。

java 中native的方法

java 中native的方法

java 中native的方法【原创版4篇】目录(篇1)1.Java 中的 native 方法概述2.native 方法的声明与调用3.native 方法的优点与局限性4.示例:使用 native 方法实现 Java 与 C 语言的交互正文(篇1)1.Java 中的 native 方法概述在 Java 语言中,native 方法是指那些不是由 Java 编译器编译而成的方法,而是由其他编程语言(如 C 或 C++)编写并编译成的本地代码。

这些本地代码可以直接在 Java 程序中调用,从而实现了 Java 与其他编程语言的交互。

native 方法主要用于实现 Java 与本地代码的交互,以完成一些 Java 语言本身无法实现或效率较低的任务。

2.native 方法的声明与调用在 Java 中,native 方法需要声明在 Java 类中,声明格式为:`native void methodName();`。

这里,methodName 为方法名,void 表示该方法不返回任何值。

需要注意的是,native 方法没有具体的实现,其实现部分需要用其他编程语言编写。

要调用 native 方法,只需在 Java 代码中像调用普通方法一样调用即可,例如:`System.loadLibrary("mylibrary");`。

这里,mylibrary 为动态链接库的名称。

3.native 方法的优点与局限性ative 方法的优点:a.可以直接调用其他编程语言编写的代码,实现 Java 与其他编程语言的交互。

b.可以使用其他编程语言提供的高效 API,提高程序的执行效率。

c.可以实现一些 Java 语言本身无法实现的功能。

ative 方法的局限性:a.不利于代码的跨平台性,因为不同平台的本地代码可能需要进行不同的修改。

b.可维护性较差,因为本地代码的修改可能导致 Java 代码的修改。

c.安全性较低,因为本地代码可以绕过 Java 的安全机制。

java jni原理

java jni原理

java jni原理Java JNI原理和使用方法一、什么是JNI?JNI(Java Native Interface)是一种允许Java代码调用本地(C/C++)代码的技术。

它提供了一种机制,使得Java程序能够与底层的原生代码进行交互,从而实现跨平台的功能。

通过JNI,我们可以在Java中调用C/C++编写的函数,同时也可以在C/C++中调用Java方法。

二、为什么要使用JNI?在某些场景下,Java语言的性能和功能可能无法满足需求。

而C/C++这样的低级编程语言在效率和灵活性方面有着明显的优势。

因此,使用JNI 可以让我们在Java中利用C/C++的优势,同时继续享受Java的跨平台特性。

三、JNI的工作原理1. 创建Java Native Method接口:首先,我们需要在Java代码中声明一个本地方法,这个方法用native关键字修饰,明确表示这个方法是由本地代码实现的。

2. 生成Java头文件:接下来,我们需要通过命令行工具`javah`来生成一个.h头文件,该文件定义了Java中声明的本地方法的接口。

3. 编写C/C++代码:根据生成的Java头文件,我们可以编写相应的C/C++代码,实现Java中声明的本地方法。

在C/C++代码中,我们可以使用JNI提供的函数和数据类型来与Java进行交互。

4. 编译本地代码生成动态链接库:将C/C++代码编译成一个动态链接库(DLL文件),以供Java程序调用。

这个动态链接库可以在不同的操作系统平台上使用。

5. 在Java程序中加载本地库:在Java程序中使用System.loadLibrary()方法来加载生成的动态链接库。

通过加载库文件,Java程序可以使用本地方法提供的功能。

6. 调用本地方法:在Java代码中,通过调用本地方法来执行C/C++代码的功能。

在调用本地方法时,JNI会负责将Java的数据类型转化为C/C++支持的数据类型以及异常处理。

java jni基本数据类型

java jni基本数据类型

java jni基本数据类型
Java JNI(Java Native Interface)允许Java代码与其他语言编写的代码进行交互,比如C、C++等。

在JNI中,Java的基本数据类型都有对应的本地(native)数据类型。

下面列出了Java基本数据类型及其对应的JNI 本地数据类型:
1. boolean: JNI使用`jboolean`来表示。

2. byte: JNI使用`jbyte`来表示。

3. char: JNI使用`jchar`来表示。

4. short: JNI使用`jshort`来表示。

5. int: JNI使用`jint`来表示。

6. long: JNI使用`jlong`来表示。

7. float: JNI使用`jfloat`来表示。

8. double: JNI使用`jdouble`来表示。

9. void: JNI使用`void`来表示。

此外,对于数组和引用类型,JNI也有相应的类型定义。

例如,`jobject`表示Java中的对象引用,而`jarray`表示Java中的数组。

注意:在JNI中,所有的本地引用类型都是用"j"作为前缀的,这有助于区分Java的原生类型和本地引用类型。

native方法

native方法

native方法
native方法是指在Java程序中调用非Java语言编写的代码的
技术。

我们知道,Java是一种基于虚拟机(JVM)的编程语言,并且具有平台无关性。

然而,有时候我们可能需要调用C、
C++、C#等其他编程语言编写的代码,这时就需要使用native
方法。

通过使用native方法,我们可以直接调用非Java语言编写的
代码,实现更高效的计算和更底层的操作。

这对于性能要求较高或者需要与底层系统交互的应用程序来说非常重要。

使用native方法的步骤如下:
1. 在Java代码中声明native方法。

需要使用native关键字修
饰方法,并且在方法体为空。

2. 使用Java编译器编译Java代码,生成对应的.class文件。

3. 使用Javah命令生成对应的头文件(.h文件)。

4. 使用C/C++编译器将头文件和C/C++代码编译成动态链接库(.dll或.so文件)。

5. 将生成的动态链接库与Java程序进行绑定,实现Java调用
非Java代码的功能。

需要注意的是,使用native方法需要时刻保持谨慎。

因为非Java代码可能涉及到底层操作,对系统资源的使用可能更加复杂。

同时,native方法调用可能引发一些安全问题,因此在使
用时需要进行严格的安全性检查。

总而言之,native方法是一种有效的技术,可以实现Java与非
Java代码的无缝衔接。

但是,需要注意在使用过程中遵循相应的规范,并确保代码的安全性和稳定性。

native在java中的用法

native在java中的用法

native在java中的用法
在Java中,native关键字用于声明一个方法是由外部环境(通常是C或C++)实现的原生方法。

native方法是一种使Java应用程序能
够与原生代码交互的手段。

与普通Java方法相比,native方法的实现不在Java代码中,而是在运行时使用本地代码实现。

当Java代码调
用一个native方法时,它会尝试在本地环境中找到该方法的实现。

由于native方法的实现依赖于特定的本地环境,因此它们不是跨
平台的。

但是,通过使用Java的JNI(Java Native Interface) API,Java应用程序可以与多种本地环境交互,包括Windows、Mac和Linux
等操作系统。

在Java中,可以通过在方法声明前添加native关键字来定义native方法:
```
public static native void myMethod();
```
除了普通的Java方法,native方法也可以被定义为实例方法:```
public native int someMethod(int arg1, String arg2);
```
在Java中使用native方法的主要优点是,它使得Java程序能够调用特定平台下的本地代码,进而可以获得性能和灵活性的优势。

但是,需要谨慎使用native方法,因为native方法可能会产生不可预测的行为和危险,例如内存泄漏和安全漏洞。

Java JNI详细学习教程

Java JNI详细学习教程

一、Java调用C/C++代码一、什么是JNIJava Native Interface(JNI)是Java语言的本地编程接口是 Java 与操作系统本地代码互相调用的功能的接口二、Java 调用C/C++步骤:1、在Java类中声明native方法新建一个Java 工程T estNativeCode 包 com.fomagic 类T estnative package com.fomagic;public class T estNative {public native void sayHello(); //C++本地代码实现public static void main(String[] args) {}}2、使用javah命令生成包含native方法定义的C/C++头文件3、按照生成的C/C++头文件来写C/C++ 源文件1) 在VS 中新建 Win32控制台应用程序–> 确定–> 下一步(即选择应用程序设置)2) 拷贝三个文件到项目目录下com_fomagic_T estNative.h 第2步生成的头文件jni.h 位于JDK 下的 include 文件目录中jni_md.h include—>win32 目录3) 添加现有项 com_fomagic_T estNative.h 引入头文件(如图)4) 新建源文件source.cpp 添加如下内容5) 注意引用的头文件“ <> ”代表从系统查找、“” “” 优先从本地查找#include "com_fomagic_T estNative.h"#include <iostream>;using namespace std;//对com_fomagic_T estNative.h 中声明的方法定义JNIEXPORT void JNICALL Java_com_fomagic_T estNative_sayHello (JNIEnv *evn, jobject obj){cout<<"Hello World !"<<endl;}4、将C/C++源文件编译成动态链接库(DLL)可执行二进制代码执行生成解决方案,在项目目录下的Debug 生成 DLL 文件5、把DLL文件所在路径添加到PATH环境变量下这个配置过Java环境变量的都应该是清楚的,这样可以方便Java程序直接调用当前的动态链接库注意:需要注意的是Eclipse开发Java程序需要重启来重新加载环境变量6、java 类中加载DLL,然后调用声明的native方法package com.fomagic;public class T estNative {public native void sayHello(); //C++本地代码实现public static void main(String[] args) {System.loadLibrary("NativeCode"); //加载动态链接库,不能加 .dllT estNative test=new T estNative();test.sayHello();}}7、运行Java 项目1) 执行结果: Hello World !2) 异常信息:Can’t load IA 32-bit .dll on a AMD 64-bit platform(大概意思就是64位的AMD 平台不能加载32 位的 .dll 文件)解决办法请百度三、弊端及注意点使用JNI,这个java Application 将不能跨平台,如果要移植到别的平台上,则 native代码需要重新进行编写java是强类型语言,而C/C++则不是,因此,必须在写JNI时更加小心在构建java程序的时候,尽量少用本地代码二、C++访问Java代码-知识点第二讲主要是介绍JNI中提供的调用和修改以及其他一些操作java代码的方法,具体如下1、Java工具生成的C/C++函数声明中,可以看到两个参数://对com_fomagic_T estNative.h 中声明的方法定义JNIEXPORT void JNICALL Java_com_fomagic_T estNative_sayHello (JNIEnv *evn, jobject obj){cout<<"Hello World !"<<endl;}JNIEnv *envJNIEnv类型可以看做是Java环境,通过这个JNIEnv* 指针,可以对Java端的代码进行操作,JNIEnv的指针会被JNI传入到本地方法的实现函数中来对Java端的代码操作例如:创建Java类的对象,调用Java对象的方法,获取Java对象的属性等<TYPE> 代表数据类型函数:NewObject/NewString/New<TYPE>Array //创建数组Get/Set<TYPE>Field //获取/设定变量属性Get/SetStatic<TYPE>Method/CallStatic<TYPE>Method … //对方法进行操作我们可以在jni.h 头文件中找到所有定义的方法:struct JNIEnv_; //定义所有方法的结构体typedef JNIEnv_ JNIEnv;………………struct JNIEnv_ {const struct JNINativeInterface_ *functions;………………jclass FindClass(const char *name) {return functions->FindClass(this, name);}………………jint GetIntField(jobject obj, jfieldID fieldID) {return functions->GetIntField(this,obj,fieldID);}}jobject obj同样也可以在jni.h 中看到对jobject 的定义表示传进来的参数为调用该方法的对象,如果是 静态native 函数,则表示native 方法坐在的类1 2 class _jobject {};typedef _jobject *jobject; //定义_jobject 类型别名 为 jobject2、Java 类型在C/C++中的映射关系这个没有什么要说的,直接看图,就是JNI 为了我方便使用定义的别名3、jclass的取得为了可以在C/C++中使用Java类jni.h头文件中专门定义了jclass类型来表示Java 中的Class类JNIEnv类中有如下几个函数取得jclassjclass FindClass(const char* clsName);jclass GetObjectClass(jobject obj);jclass GetSuperClass(jclass obj);FindClass会在classpath系统环境变量下找类传入完整类名,注意包与包之间用”/” 而不是”.”来连接如:jclass cls_string=env->Fin dClass(“java/lang/String”);4、访问Java类中的属性和方法在C/C++本地代码中访问Java端的代码,一个常见的应用就是获取类的属性和调用类的方法,为了在C/C++中表示属性和方法,JNI在jni.h 头文件中定义了jfieldID、jmethodID 类型来分别代表Java端的属性和方法在访问设置Java 属性和方法时,首先在本地代码获取代表Java属性的jfieldID 和jmethodID 然后进行Java属性和方法的操作JNIEnv中 GetFieldID/GetMethodID GetStaticFieldID/GetStaticMethodID 获取如:env->GetMethodID(data_Clazz,”<int>”,”()V”); // ()V指无返回类型void,下面讲到5、Sign是什么?例如T estNative.java中有两个重载方法:package com.fomagic;public class T estNative {public void function(int i){System.out.println("Integer: "+i);}public void function(double d){System.out.println("Double: "+d);}}当在C++中调用其中一个函数的时候,就需要按照以下步骤:获取函数所在类jclass clazz_T estnative=env->FindClass(“com/fomagic/T estNative”);2、获取方法的jmethodID 来调用方法jmethodID id_func =env->GetMethodID (clazz_T estnative,”function”,” (I)V”);->GetMethodID (clazz_T estnative,”function”,”(D)V”);其中通过指定函数的参数类型和返回值类型来返回jmethodID,从而对应的函数,这就是sign以下是对应类型:6、使用javap命令生成签名JDK中提供了javap工具来查看类的声明,可以输出每个方法与属性的签名package com.fomagic;import java.util.Date;public class T estNative {public native void sayHello(); //C++本地代码实现public static void main(String[] args) {System.loadLibrary("NativeCode");//加载动态链接库,不能加.dllT estNative test=new T estNative();test.sayHello();}public int property;public int function(int foo,Date date, int[] arr){return 0;}}我们对上面代码通过javap 工具直接生成方法和属性的签名:1、命令行定位到该类的绝对路径 cd T estNativeCode\bin 目录2、执行javap -s -private com.fomagic.T estnativejavap -s -p… [完整类名]注:private获取全部权限的成员、public获取public修饰的成员 (即获取大于或等于自己权限的成员方法或属性)三、C++操作java属性和方法在第二讲中讲到了C++中操作java程序的方法以及操作步骤,下面就通过实例的方式来体会到底怎么通过JNI提供的方法来获取、操作java属性、方法以及父类方法1、取得/设定Java属性值在原来java 类T estNative的基础上编写如下代码:package com.fomagic;public class T estNative {public native void sayHello(); //C++本地代码实现public int number=10; //定义变量初始值为10,在C++中进行修改public static void main(String[] args) {System.loadLibrary("NativeCode");//加载动态链接库,不能加.dllT estNative test=new T estNative(); //创建本类实例test.sayHello();System.out.println("C++中操作之后的结果:"+test.number);}}C++中原有代码添加如下:JNIEXPORT void JNICALL Java_com_fomagic_T estNative_sayHello (JNIEnv *env, jobject obj){cout<<"Hello World !"<<endl;jclass clazz_T estNative=env->GetObjectClass(obj); //通过传入的obj类的对象获取当前类jfieldID id_number=env->GetFieldID(clazz_T estNative,"number","I"); //类实例,属性名,(sign)数据类型jint number =env->GetIntField(obj,id_number); // 通过ID 获取当前变量cout<<"原数据:"<<number <<endl;env->SetIntField(obj,id_number,100L); //类实例,变量ID, 修改的java属性值}注:修改的属性值100L,可以参看第二讲的“Java类型在C/C++中的映射关系” 图表(java中 int 对应C++中long)2、调用Java类的方法调用实例方法的三种形式;Call<TYPE>Method(jobject obj ,jmethodID id ,….);Call<TYPE>MethodV(jobject obj ,jmethodID id ,va_list lst);Call<TYPE>Method(jobject obj ,jmethodID id ,jvalue* v) ;第一个比较常用第二个是当调用这个函数有一个指向参数表的va_list变量时使用(只知道是可变参数列表) 第三个当调用函数时有一个指向jvalue或jvalue数组的指针时使用(即传入的是所有参数的变量数组指针)下面就以第一种方式写下返回较大值的实例:package com.fomagic;public class T estNative {public native void sayHello(); //C++本地代码实现public static void main(String[] args) {System.loadLibrary("NativeCode");//加载动态链接库,不能加.dllT estNative test=new T estNative();test.sayHello();}double max(double num1,double num2){return num1>num2 ? num1 : num2;}}JNIEXPORT void JNICALL Java_com_fomagic_T estNative_sayHello (JNIEnv *env, jobject obj){jclass clazz_T estNative=env->GetObjectClass(obj); //获取当前类jmethodID id_max=env->GetMethodID(clazz_T estNative,"max","(DD)D"); //获取方法ID(签名)jdouble maxValue = env->CallDoubleMethod(obj,id_max,100.5,203.1); //调用max方法进行传值cout<<"较大值:"<<maxValue <<endl; }3、调用Java类父类方法我们都知道在java中父类创建子类对象只能调用子类的覆盖方法,而C++中子类对象默认调用的父类的方法,当父类方法用虚拟函数关键字virtual修饰时,调用子类覆盖方法通过JNI的 CallNonvirtual<TYPE>Method 可以实现子类对象调用父类被覆盖的方法的功能,步骤:取得父类和需要调用的父类中方法的jmethodID将jmethodID传入 CallNonvirtual<TYPE>Method代码:新建Father类、Child类package com.fomagic;public class T estNative {public native void sayHello(); // C++本地代码实现public Father p=new Child(); //创建Child 的实例对象public static void main(String[] args) {System.loadLibrary("NativeCode");// 加载动态链接库,不能加 .dllT estNative test = new T estNative();test.sayHello();}}class Father {public void function() {System.out.println("Father function");}}class Child extends Father {public void function() {System.out.println("Child function");}}JNIEXPORT void JNICALL Java_com_fomagic_T estNative_sayHello (JNIEnv *env, jobject obj){jclass clazz_T estNative=env->GetObjectClass(obj);jfieldID id_p=env->GetFieldID(clazz_T estNative,"p","Lcom/fomagic/Father;");jobject p= env->GetObjectField(obj,id_p);jclass clazz_Father = env->FindClass("com/fomagic/Father");jmethodID id_Father_function= env->GetMethodID(clazz_Father,"function","()V");//env->CallVoidMethod(p,id_Father_function);;env->CallNonvirtualVoidMethod(p,clazz_Father,id_Father_function);}四、(1)在C++中创建Java对象本节讲的是在C/C++本地代码中创建Java对象,JNI 中提供两个方法进行Java对象的操作,分别是 NewObject 和 Allocobject,先看下jni.h 头文件中对两个方法的定义jobject NewObject(jclass clazz, jmethodID methodID, ...) {va_list args;jobject result;va_start(args, methodID);result = functions->NewObjectV(this,clazz,methodID,args);va_end(args);return result;}jobject AllocObject(jclass clazz) {return functions->AllocObject(this,clazz);}1、NewObject 创建Java对象GetMethodID 能够获取构造方法的jmethod,如果传入的要取得的方法名称设定为”<init>”就能取得构造方法构造方法没有返回值,签名始终为Void (()V)下面是一个通过C++创建Java的Date对象并在Java控制台输出1970到现在毫秒数package com.fomagic;public class T estNative {public native void sayHello(); // C++本地代码实现public static void main(String[] args) {System.loadLibrary("NativeCode");// 加载动态链接库,不能加 .dllT estNative test = new T estNative();test.sayHello();}}JNIEXPORT void JNICALL Java_com_fomagic_T estNative_sayHello (JNIEnv *env, jobject obj){jclass clazz_date = env->FindClass("java/util/Date"); //找到Date类jmethodID id_date= env->GetMethodID(clazz_date,"<init>","()V"); //通过类获取构造方法ID,默认无返回值jobject now=env->NewObject(clazz_date,id_date); //创建Date的实例对象jmethodID id_date_getTime=env->GetMethodID(clazz_date,"getTime","()J"); //获取Date类的getTime()方法的ID,返回值是long 即JNI中对应的J jlong time = env->CallLongMethod(now,id_date_getTime); //通过now对象调用getTime()方法,得到时间cout<<time<<endl;}代码很简单通过前面的知识都是可以明白的,注释应该没什么问题(吧)2、Allocobject创建Java对象使用函数AllocObject 可以根据传入的jclass创建一个Java对象但他的状态是非初始化的,在使用这个对象之前绝对要用CallNovirtualVoidMethod来调用该jclass的建构函数,这样可以延迟构造函数的调用,这一部分用的很少(对于这个函数到底是什么意思,我也没有完全搞明白,只是知道这样用,以后慢慢研究) jclass clazz_str =env->FindClass("java/lang/String");jmethodID methodID_str=env->GetMethodID(clazz_str,"<init>","([C)V");//获取构造jObject string =env->AllocObject(clazz_str);// 预先创建没有初始化的字符串jcharArray arg=env->NewCharArray(4); //创建长度为4的字符数组env->SetCharArrayRegion(arg,0,4,L"奇幻未来"); //复制"奇幻未来"到数组arg中env->CallNonvirtualVoidMethod(string,clazz_str,methodID_str,arg); //讲arg字符数组复制给stringjclass clazz_this=env->GetObjectClass(obj);// 这是视频中假设这个对象的类中有定义static String STATIC_STR;jfieldIDfieldID_str=env->GetStaticFieldID(clazz_this,"STATIC_STR","Ljava/lang/String;"); env->SetStaticObjectField(clazz_str,fieldID_str,string);四、(2)C++访问Java的String字符串对象我以前是学Java的,对于C++只是明白很少的知识,所以看得越多,出现的问题也越多,我只有慢慢消化了第四讲的第二部分:在C/C++本地代码中访问Java的String字符串对象Java与C++中字符串的区别在Java中,使用的字符串String 对象时Unicode(UTF-16)码,即每个字符不论是中文还是英文还是符号,一个字符总是占两个字节Java通过JNI接口可以将Java的字符串转换到C/C++的宽字符串(wchar_t*),或是传回一个UTF-8的字符串(char*)到C/C++.C/C++可以通过一个看字符串或是一个UTF-8编码的字符串来创建一个Java端的String对象JNI中操作字符串相关函数函数作用是取得某个jstring对象相关的Java字符串,介绍了三种类型的字符串操作函数1、GetStringChars 与 GetStringUTFCharsGetStringChars 取得UTF-16编码的宽字符串(jchar*)GetStringUTFChars 取得UTF-8编码的字符串(char*)const jchar *GetStringChars(jstring str, jboolean *isCopy) {return functions->GetStringChars(this,str,isCopy);}const char* GetStringUTFChars(jstring str, jboolean *isCopy) {return functions->GetStringUTFChars(this,str,isCopy);}void ReleaseStringChars(jstring str, const jchar *chars) {functions->ReleaseStringChars(this,str,chars);}void ReleaseStringUTFChars(jstring str, const char* chars) {functions->ReleaseStringUTFChars(this,str,chars);}1 )、参数第一个参数传入一个指向Java中的String对象的jstring变量.第二个参数传入jboolean 指针,标示是否对Java的String对象进行了Copy。

jni 调用原理

jni 调用原理

jni 调用原理JNI调用原理介绍JNI(Java Native Interface)是Java提供的一种机制,用于实现Java代码与其他编程语言(如C、C++)进行交互。

它提供了一组API,允许Java程序调用Native代码,以及Native代码调用Java代码。

本文将从浅入深地解释JNI调用的原理。

JNI基本概念•Java Native Method:Java程序中声明的能够被Native代码调用的方法。

•Java Native Interface:为Java程序和Native代码之间的交互提供了一套规范。

•Native Library:包含Native代码的动态链接库(.dll或.so 文件),提供给Java程序加载和调用。

•JNI Environment:Java调用Native代码时的运行环境,提供了JNI函数库的函数方法。

JNI调用过程1.编写Native方法的声明在Java程序中,使用native关键字来声明可以被Native代码调用的方法。

2.生成JNI头文件通过Java的javah命令,对包含Native方法的类进行处理,生成对应的JNI头文件。

3.编写Native代码使用C或C++等编程语言,编写与JNI头文件中声明的方法对应的Native实现代码。

4.编译Native代码将Native代码编译为动态链接库文件,例如.so文件。

5.加载Native库在Java代码中使用()方法加载编译好的Native库。

6.执行JNI调用通过JNI函数库的函数方法,进行Java和Native代码之间的调用。

Java代码通过JNI方法接口调用Native方法,Native代码通过JNI环境接口调用Java方法。

JNI接口JNI接口是Java和Native代码之间通信的桥梁。

JNI提供了一套函数库,包含了丰富的函数方法,用于数据类型转换、异常处理、线程管理等。

常用的JNI函数方法包括: - JNIEnv:JNI环境接口,提供了与Java运行时环境交互的一系列函数方法。

java native 方法

java native 方法

java native 方法Java Native方法是一种特殊的方法,它允许Java应用程序调用本地库中的原生代码,实现对底层系统的访问,从而提高代码的执行效率。

Java Native方法可以是静态或非静态的本地方法,由本地代码实现的方法可以使用Java Native Interface(JNI)来调用。

Java Native方法可以用于访问系统资源、处理文件、访问硬件设备或优化数学计算等处理。

Java Native方法能够使用高效的本地代码来提高Java程序的执行效率,因为它们避免了JVM的内存管理开销,从而减少了JVM的运行时间。

Java Native方法还可以与其他语言和技术进行交互,例如C++和OpenGL等技术。

Java Native方法需要满足一定的要求和约束条件,其中包括Java Native方法的签名必须符合JNI规范,必须在Java代码中定义本地方法,并使用native关键字将其标识为本地方法。

Java Native方法的本地实现必须通过JNI接口与Java虚拟机进行交互,以便在Java代码中调用。

Java Native方法的编写和使用需要一定的编程经验和技能,包括对C语言、JNI接口和本地库的熟悉度。

Java Native方法可以为Java应用程序提供访问本地功能的能力,从而扩展Java的能力。

同时,Java Native方法还需要谨慎使用,因为它们与JVM进行交互,可能会导致安全问题和内存泄漏问题。

总之,Java Native方法是Java语言的一个重要特性,它可以为Java 开发人员提供访问本地资源和功能的能力,提高Java程序的执行效率和性能。

但是,Java Native方法需要满足一定的要求和约束条件,并且需要谨慎使用,以避免安全问题和内存泄漏问题。

对于Java开发人员而言,学习和掌握Java Native方法是很有必要的,这样可以更好地利用Java的优势和特性,提高开发效率和应用程序的性能。

java jni方法

java jni方法

java jni方法Java JNI方法是Java Native Interface的简称,是一种用于在Java程序中调用本地C/C++代码的技术。

JNI方法允许开发者在Java程序中使用底层的本地库函数,实现高性能和跨平台的功能。

本文将为您介绍JNI方法的基本概念、使用方法以及相关注意事项。

JNI方法是Java与本地代码之间进行通信的桥梁。

通过JNI方法,Java程序可以直接调用本地C/C++库中的函数,实现对底层资源的访问,以及实现高性能的计算任务。

JNI方法在开发需要访问底层硬件、操作系统级别的功能、调用系统级别库函数等情况下非常有用。

要使用JNI方法,首先需要在Java代码中声明native关键字。

native关键字告诉编译器这个方法将在本地代码中实现。

然后,在本地代码中实现相应的函数,函数名称要与Java中声明的方法名称一致。

在Java代码中,可以使用`System.loadLibrary("library_name")`方法加载本地库。

这个方法会在本地系统路径中查找并加载指定名称的库文件。

一旦库文件加载成功,就可以通过调用声明为native的Java方法来调用本地代码。

为了在Java代码中调用本地函数,需要使用JNI提供的接口函数。

JNI接口函数提供了一系列函数用于在Java和本地代码之间传递参数、调用本地函数以及处理返回值。

这些函数包括`JNIEnv`和`JavaVM`等。

使用JNI方法需要注意以下几点。

首先,本地代码必须与Java代码在相同的平台以及编译器下进行编译。

其次,在使用JNI方法时,应考虑到跨平台的兼容性,避免使用与特定平台相关的功能。

此外,开发者还需要注意内存管理的问题,避免出现内存泄漏或者内存溢出等问题。

总之,JNI方法为Java开发者提供了一个与本地代码进行交互的桥梁,可以实现更高效、更灵活的功能。

然而,使用JNI方法需要开发者具备一定的本地编程能力,并且注意到与平台和兼容性相关的问题。

java中的native方法

java中的native方法

java中的native方法嘿,朋友们!今天咱来聊聊 Java 中的 native 方法。

这玩意儿啊,就像是 Java 世界里的一个神秘通道。

你想想看,Java 就像是一个有着各种规则和秩序的大王国,它自己有一套完整的运行体系。

但有时候呢,这个王国也需要和外面的世界打交道呀,这时候 native 方法就派上用场啦!它就像是王国开向外界的一扇门,可以让 Java 代码和其他语言编写的代码进行交流和合作。

比如说,在一些对性能要求特别高的场景下,native 方法就能大展身手啦!它可以直接调用底层的系统资源,那速度,可比普通的 Java 代码快多啦!这就好比跑步比赛,普通方法是一步一步跑,而 native 方法呢,就像是开着赛车在飞奔!而且哦,native 方法还能让 Java 利用一些现有的、非常成熟的底层库。

这可太棒啦,不用自己从零开始去开发那些复杂的功能,直接拿来用就行,多省事呀!这就好像你要盖房子,别人已经有了坚固的基石和现成的材料,你直接用不就好啦,何必自己费力去从头弄呢?但是,可别以为 native 方法就是无敌的啦!它也有自己的一些小麻烦呢。

比如说,它的调试可不像普通 Java 代码那么容易哦。

毕竟它涉及到和其他语言的交互,一旦出了问题,那可真是让人头疼呀!就像你开着一辆很酷炫但有点复杂的车,出了故障修起来可不简单。

还有啊,使用 native 方法也要小心一些兼容性的问题呢。

不同的操作系统、不同的硬件环境,都可能会对它产生影响。

这就像是你在不同的道路上开车,有的路平坦好走,有的路却坑坑洼洼,得小心应对才行呢!不过呢,总的来说,native 方法在 Java 中可是有着很重要的地位呀!它就像一把钥匙,能打开很多新的可能性和机会。

它让 Java 变得更加强大,更加灵活,能应对更多复杂的场景和需求。

所以呀,我们可不能小瞧了这个 native 方法哦!它虽然有点神秘,但只要我们好好去了解它、掌握它,就能让它为我们的编程之旅增添不少色彩呢!你说是不是呀?嘿嘿!。

Java中的Native方法

Java中的Native方法

Java中的Native⽅法⽬录1.Native⽅法在Java中如何⼯作?2.Java中Native⽅法的⽰例3.总结以下是java中如何使⽤native⽅法的基本语法:[ public / protected / private] native [return-type] methodName ();上⾯的语法显⽰了如何在java中声明本机⽅法。

与普通⽅法⼀样,它需要定义⼀个访问修饰符,后跟⼀个native关键字,后跟⽅法的返回类型,最后是⽅法名称,如果需要,还需要指定输⼊参数。

1.Native⽅法在Java中如何⼯作?它可以定义为那些⽤java以外的语⾔(如C/C++)实现的⽅法。

使⽤这些⽅法背后的总体思路可能是利⽤C/C++中提供的⾼性能或内存管理。

为了⽀持⽤其他语⾔编写的⽅法,Java提供了⼀个称为Java Native Interface的接⼝,它充当Java和其他语⾔之间的中介。

使⽤JNI的动机来⾃这样⼀个事实:它可以提供代码重⽤性和⾼性能。

需要注意的是,⽤C/C++等其他语⾔编写的代码是不可移植的。

以下是Java本机native接⼝的主要组件:javah:这是java开发⼯具包中提供的⼀个⼯具,它从包含native⽅法的现有java⽂件java类中创建与C兼容的头⽂件。

h:这是Java开发⼯具包中提供的基于C/C++的头⽂件,其功能是提供Java数据类型和native数据类型之间的映射。

上⾯描述的Javah⽂件⾃动⽣成这个⽂件。

2.Java中Native⽅法的⽰例现在我们将看到⼀个⽰例,它将清楚地了解native⽅法在java中的⼯作⽅式。

以下是使⽤native⽅法所涉及的步骤:1. 编程java代码。

2. 编译java代码。

3. 创建⼀个C头⽂件。

4. 在C/C++中实现native⽅法逻辑。

5. 创建⼀个共享库。

6. 运⾏并测试java应⽤程序。

下⾯的⽰例将分为两部分:具有java代码和具有native代码。

javanative方法与JNI实现

javanative方法与JNI实现

javanative⽅法与JNI实现native⽅法定义:简单地讲,⼀个Native Method就是⼀个java调⽤⾮java代码的接⼝。

⼀个Native Method是这样⼀个java的⽅法:该⽅法的实现由⾮java 语⾔实现,⽐如C。

这个特征并⾮java所特有,很多其它的编程语⾔都有这⼀机制,⽐如在C++中,你可以⽤extern "C"告知C++编译器去调⽤⼀个C的函数。

VM怎样使Native Method跑起来:我们知道,当⼀个类第⼀次被使⽤到时,这个类的字节码会被加载到内存,并且只会回载⼀次。

在这个被加载的字节码的⼊⼝维持着⼀个该类所有⽅法描述符的list,这些⽅法描述符包含这样⼀些信息:⽅法代码存于何处,它有哪些参数,⽅法的描述符(public之类)等等。

如果⼀个⽅法描述符内有native,这个描述符块将有⼀个指向该⽅法的实现的指针。

这些实现在⼀些DLL⽂件内,但是它们会被操作系统加载到java程序的地址空间。

当⼀个带有本地⽅法的类被加载时,其相关的DLL并未被加载,因此指向⽅法实现的指针并不会被设置。

当本地⽅法被调⽤之前,这些DLL才会被加载,这是通过调⽤java.system.loadLibrary()实现的。

JNI实现本地⽅法:1.参考⽂献:参考1:参考2:参考3:2.概述今天在看多线程编程的时候,发现Thread这个类中有多个native⽅法,以前从来没有见过这种⽅法,因此对于⽐较好奇,查阅了⼀些资料,现在整理⼀下,以作备忘。

2.1.native关键字⽤法native是与C++联合开发的时候⽤的!使⽤native关键字说明这个⽅法是原⽣函数,也就是这个⽅法是⽤C/C++语⾔实现的,并且被编译成了DLL,由java去调⽤。

这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。

对于不同的平台它们也是不同的。

这也是java的底层机制,实际上java就是在不同的平台上调⽤不同的native⽅法实现对操作系统的访问的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Java中native方法和JNI基础
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。

可以将native方法比作Java程序同C程序的接口,其实现步骤:1、在Java中声明native()方法,然后编译;
2、用javah产生一个.h文件;
3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);
4、将第三步的.cpp文件编译成动态链接库文件;
5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。

JAVA本地方法适用的情况
1.为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问
2.为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的
3.为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。

首先写好JAVA文件
/*
* Created on 2005-12-19 Author shaoqi
*/
package com.hode.hodeframework.modelupdate;
public class CheckFile
{
public native void displayHelloWorld();
static
{
System.loadLibrary("test");
}
public static void main(String[] args) {
new CheckFile().displayHelloWorld();
}
}
然后根据写好的文件编译成CLASS文件
然后在classes或bin之类的class根目录下执行javah
-jnicom.hode.hodeframework.modelupdate.CheckFile,
就会在根目录下得到一个
com_hode_hodeframework_modelupdate_CheckFile.h的文件然后根据头文件的内容编写
com_hode_hodeframework_modelupdate_CheckFile.c文件#include "CheckFile.h"
#include
#include
JNIEXPORT void JNICALL
Java_com_hode_hodeframework_modelupdate_CheckFile_displayH elloWorld(JNIEnv *env, jobjectobj)
{
printf("Hello world!\n");
return;
}
之后编译生成DLL文件如“test.dll”,名称与
System.loadLibrary("test")中的名称一致
vc的编译方法:cl -I%java_home%\include
-I%java_home%\include\win32 -LD
com_hode_hodeframework_modelupdate_CheckFile.c -Fetest.dll 最后在运行时加参数-Djava.library.path=[dll存放的路径]
JNI入门:
本文讲述如何使用JNI技术实现HelloWorld,目的是让读者熟悉JNI 的机制并编写第一个HelloWorld程序。

Java Native Interface(JNI)是Java语言的本地编程接口,是J2SDK 的一部分。

在java程序中,我们可以通过JNI实现一些用java语言不便实现的功能。

通常有以下几种情况我们需要使用JNI来实现。

∙标准的java类库没有提供你的应用程序所需要的功能,通常这些功能是平台相关的
∙你希望使用一些已经有的类库或者应用程序,而他们并非用java语言编写的
∙程序的某些部分对速度要求比较苛刻,你选择用汇编或者c语言来实现并在java语言中调用他们
在《java核心技术》中,作者提到JNI的时候,建议不到万不得已不要使用JNI技术,一方面它需要你掌握更多的知识才可以驾驭,一方面使用了JNI你的程序就会丧失可移植性。

在本文我们跳过JNI的底层机制,读者最好先把它想象为本地代码和java代码的粘合剂。

关系如下图所示:
下面我们开始编写HelloWorld程序,由于涉及到要编写c/c++代码因此我们会在开发中使用Microsoft VC++工具。

1. 编写java代码
我们在硬盘上建立一个hello目录作为我们的工作目录,首先我们需要
编写自己的java代码,在java代码中我们会声明native方法,代码非常简单。

如下所示
class HelloWorld
{
public native void displayHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
注意我们的displayHelloWorld()方法的声明,它有一个关键字native,表明这个方法使用java以外的语言实现。

方法不包括实现,因为我们要用c/c++语言实现它。

注意System.loadLibrary("hello")这句代码,它是在静态初始化块中定义的,系统用来装载hello共享库,这就是我们在后面生成的hello.dll(如果在其他的操作系统可能是其他的形式,比如hello.so)
2. 编译java代码
javac HelloWorld.java 生成HelloWorld.class文件
3. 创建.h文件
这一步中我们要使用javah命令生成.h文件,这个文件要在后面的c/c++代码中用到,我们运行
javahHelloWorld。

这样我们可以看到在相同目录下生成了一个
HelloWorld.h文件,文件内容如下
在此我们不对他进行太多的解释。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: displayHelloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
4. 编写本地实现代码
在这部分我们要用C/C++语言实现java中定义的方法,我们在VC++中新建一个Project,然后创建一个HelloWorldImp.cpp文件,内容如下#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobjectobj)
{
printf("Hello world!\n");
return;
}
注意我们这里include了jni.h和刚才得到的HelloWorld.h文件。

因此你要在VC++里面设置好,jni.h在JAVA_HOME/include里面。

编译通过后再生成hello.dll文件。

5. 运行java程序
把上面生成的hello.dll文件复制到我们的工作目录,这时候我们的目录
中包括HelloWorld.java,HelloWorld.class和hello.dll文件。

运行java HelloWorld命令,则可在控制台看到Hello world|
的输出了。

相关文档
最新文档