Java本地接口(Java Native Interface (JNI))允许运行在Java虚拟机(Java Virtual Machine (JVM))上的代码调用本地程序和类库,或者被它们调用,这些程序和类库可以是其它语言编写的,比如C、C 或者汇编语言。
当一个程序无法完全使用Java编写时,开发者可以通过JNI来编写本地方法,比如标准Java类库并不支持的依赖于平台的特色或者程序库。JNI还可以用于修改现有的使用其它语言编写的程序,使它们可以通过Java编写的程序来访问。
很多基本类库都依赖JNI来为开发者和用户提供服务,比如文件的输入/输出和音频功能。在基本类库中包含的对于性能和平台敏感的API可以允许所有的Java程序以安全和平台无关的方式来使用这些功能,在采用JNI之前,开发者需要明确这些功能并不是已经包含在Java标准类库中的,在这篇文章中,我将会讲解JNI是如何工作的以及本地类型是如何映射到Java的类型和类库的。
JNI工作原理
在JNI中,本地函数是通过一个独立的.c或.cpp文件来实现的(C 为JNI提供的界面会更简洁一些)。当JVM调用该函数时,它传递了一个JNIEnv指针、一个jobject指针和通过Java方法定义的Java参数,JNI函数的形式如下:
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobjectobj)
{
//Method native implemenation
}
env指针是一个包含了JVM接口的结构,它包含了与JVM进行交互以及与Java对象协同工作所必需的函数,示例中的JNI函数可以在本地数组和Java数组类型之间、本地字符串和Java字符串类型之间进行转换,其功能还包括对象的实例化、抛出异常等。基本上您可以使用JNIEnv来实现所有Java能做到的事情,虽然要简单很多。
更加正式的解释是这样的,本地代码通过调用JNI的函数来访问JVM,这是通过一个界面指针实现的(界面指针实际上是指向指针的指针),该指针指向一个指针数组,数组中的每个指针都指向了一个界面函数,而每个界面函数都是在数组中预先定义过的。
本地方法将JNI界面指针当作一个参数,如果在同一个Java线程中,出现对该本地方法的多重调用,JVM则保证传递相同的界面指针到本地方法。不过,一个本地方法可以被不同的Java线程调用,因而也可能会收到不同的JNI界面指针。
本地方法是通过System.loadLibrary方法加载的,在以下的例子中,类的初始化方法加载了一个指定平台的本地类库,该类库定义了本地方法:
packagepkg;
class Cls {
native double f(inti, String s);
static {
System.loadLibrary(pkg_Cls");
}
}
System.loadLibrary方法的参数是一个类库的名称,它可以由程序员任意选取,系统则遵循一个标准的本地化平台的方式来转换类库的名称到一个本地类库的名称。例如,在Solaris操作系统中会将pkg_Cls转换为libpkg_Cls.so,而Win32系统则会将同样的pkg_Cls转换为pkg_Cls.dll。
动态指针会根据它们的名字来进行解析,一个本地方法的名称是按照组件进行连接的,它包含了:前缀“Java_”、一个分离的合法的类名称和一个分离的方法名称。
注意:微软的JVM有相同的机制从Java调用本地Windows代码,该机制被称为原始本地接口(Raw Native Interface (RNI))。
数据类型映射
基本类型,比如整型、字符等等,是在Java和本地代码间进行拷贝的,而其他的自定义Java对象则是通过引用来传递的。
这个表格展示了Java和本地代码之间的类型映射,这些类型是可以互换的,您可以在您使用int类型的位置使用jint类型,当然反过来也一样,而且不需要任何类型转化。但是,Java的字符串和数组类型和本地的字符串与数组类型之间的转换就比较困难了,如果您使用的jstring类型中出现了字符“*”,您的代码会造成JVM的崩溃,以下的例子说明了您应当如何正确使用字符串:
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobjectobj, jstringjavaString)
{
//Get the native string from Java string
const char *nativeString = env->GetStringUTFChars(env,javaString, 0);
printf("%s", nativeString);
env->ReleaseStringUTFChars(env,javaString, nativeString);
}
您需要使用界面指针env来操作Java对象。
总结
在您的程序中使用JNI并不是一件容易的事情,然而,JNI的性能和使用原有代码的能力将会为您的Java程序添加更多的功能并且能胜任更多的挑战,如果需要关于JNI的更多信息,可以访问JNI的主页。
分享到:
相关推荐
开发者首先需要使用`javah`工具(在JDK中)处理Java源文件,生成JNI头文件。头文件包含了Java类和方法的本地声明,使得C++代码可以调用Java的方法。 3. **编写C++代码**: 在生成的头文件中,开发者可以找到Java...
标题中的"DELPHI开发JNI必备 jni.pas"表明这是一个针对Delphi开发者的资源,其中包含的`jni.pas`文件是用Delphi编写的,目的是支持在Delphi项目中使用JNI来调用本地C/C++库或Java方法。`jni.pas`通常会封装JNI的C...
通常,`jni_md.h`被`jni.h`包含,并且在编译时由JDK自动选择合适的版本。 Java调用C和C++函数时,JNI提供了统一的接口,但两者之间还是有一些差异。C++支持类和对象,因此在C++中使用JNI时,可以利用C++的特性,如...
Android NDK(Native Development Kit)则是一个工具集,允许开发者使用C/C++编写部分应用程序,然后通过JNI与Java代码进行交互。 步骤一:创建本地方法 在Java源代码中,我们需要声明本地方法,这是Java代码调用C/...
这个文件通常由JDK在编译时自动生成,并且被`jni.h`包含进来。开发者一般不需要直接处理`jni_md.h`,因为`jni.h`已经处理了所有跨平台的兼容性问题。 使用JNI时,开发流程通常包括以下步骤: 1. **编写本地方法**:...
今天整理垃圾代码,删除之前发现了JNI的一个Delphi版本。 开源项目具体没记录。关键是Demo可以直接编译并运行。而且代码中包含JNI文件。
在开始使用JNI之前,你需要确保已经安装了JDK,并且配置了相应的环境变量。此外,还需要安装C/C++的编译器,如GCC,用于编译本地代码。在Windows上,你可能还需要下载并安装Visual Studio或MinGW。 三、创建Java...
Java(JDK17)通过JNI实现调用C++动态链接库- CMake模块化项目管理
标题中的"window JDK1.5 32位 绿色免安装版"指的是适用于Windows操作系统的32位版本的JDK 1.5,它是一个便携式版本,无需正式安装即可使用。这种绿色免安装版通常是为了方便开发者在不同机器间快速切换工作环境,或...
在Ubuntu操作系统上使用JNI,通常是为了解决Java在某些特定任务上的性能瓶颈或者利用已有的C/C++库。这个"ubuntu上面使用jni例子"的压缩包很可能是提供了一个在Ubuntu环境下开发和运行JNI程序的示例。 JNI的核心...
1. 找不到jni.h文件:该问题可以通过将jdk的bin目录和include目录添加到编译环境中来解决。 2. 动态链接库加载失败:该问题可以通过检查动态链接库的路径和名称来解决。 Jni是一种powerful技术,allowing Java程序...
`jni_md.h`头文件是与特定平台相关的,通常由JDK自动生成,包含了针对不同操作系统和处理器架构的特定数据类型定义和函数原型。例如,在32位Windows平台上,它可能会定义`jint`为`int`,而在64位Linux上可能定义为`...
说明:作为Java程序员,当与c程序员进行联合开发时会使用到JNI编程技术。此时要求Java程序员必须要会使用dll文档,以使用调试Java代码。这里介绍使用Windows OS自带的c/c++编译器(cl)怎样把.c文档编译成.exe和.dll...
开发者需要使用JDK提供的`javah`工具生成对应的C/C++头文件,这个头文件包含了JNI函数的声明。本地方法接口定义了一组JNI函数,例如`FindClass`, `GetMethodID`等,用于在本地代码中操作Java对象和类。环境指针...
- **生成JNI头文件**:使用`javah`工具(在较新版本的JDK中,可能需要使用`javac -h`)根据Java类生成对应的JNI头文件,例如`JNICallback.h`。 - **实现JNI方法**:在C/C++代码中,实现JNI头文件中声明的函数。...
2. **环境设置**:学习JNI的第一步通常是配置开发环境,包括安装JDK,设置Java开发工具链,以及为C/C++编译器配置相应的头文件和库。这一步也涉及到如何创建和注册本地方法,以及编写JNI头文件。 3. **调用C/C++...
2. **生成JNI头文件**:使用`javah`工具(在JDK的bin目录下)根据Java类生成对应的C/C++头文件。例如: ```bash javah -jni NativeDemo ``` 这会生成一个`NativeDemo.h`文件,其中包含了Java方法的C/C++声明。 3. *...
标题 "JDK8 给unity使用的" 暗示了这个压缩包包含了Java Development Kit (JDK) 的第8个主要版本,这是用于开发和运行Java应用程序的重要工具集。Unity,另一方面,是一个流行的跨平台游戏引擎,常用于创建2D和3D...
- `include`:包含了头文件,供C或C++程序员使用JNI(Java Native Interface)来编写本地方法。 4. JDK 1.8的关键特性: - Lambda表达式:引入函数式编程概念,简化多线程和事件驱动编程。 - Nashorn JavaScript...