이 글은 주로 Java 로컬 인터페이스 JNI 사용법에 대한 관련 정보를 자세하게 소개하고 있으니, 이 글을 통해 JNI 프로그래밍을 제대로 활용하시기 바랍니다. 인터페이스 JNI
Java 프로그램에 대해 직원들에게 Java 언어의 장점과 이점을 설명할 필요는 없을 것 같습니다. 누구나 자연스럽게 많은 것을 알려줄 것입니다. 그러나 우리는 Java 프로그래머로서 Java 언어에도 몇 가지 단점이 있다는 점을 인정해야 합니다. 예를 들어 성능 측면과 기본 레이어 처리 측면에서 단점이 있습니다. 따라서 Java는 일부 로컬 인터페이스를 제공하며, 주요 기능은 Java 프로그램이 가상 머신을 통해 네이티브 코드와 상호 작용할 수 있는 표준 방법을 제공하는 것입니다. Java Virtual Machine(VM) 내에서 실행되는 Java 코드가 C, C++, 어셈블리 언어 등 다른 프로그래밍 언어로 작성된 애플리케이션 및 라이브러리와 상호 운용될 수 있도록 합니다. JNI의 가장 중요한 이점은 기본 Java 가상 머신의 구현에 제한을 두지 않는다는 것입니다. 따라서 Java 가상 머신 공급업체는 가상 머신의 다른 부분에 영향을 주지 않고 JNI에 대한 지원을 추가할 수 있습니다. 프로그래머는 모든 JNI 지원 Java 가상 머신에서 작동하는 기본 애플리케이션 또는 라이브러리의 한 버전만 작성하면 됩니다. 네이티브 코드와 상호 작용해야 하는 이유를 살펴보겠습니다.
One: 애플리케이션 성능 향상.
우리는 java가 c/c++ 및 어셈블리 언어에 비해 상대적으로 "고급"이라는 것을 알고 있습니다. 실제로 여기서 고급 기능은 프로그래머의 작업을 단순화하는 것입니다. 많은 하위 수준 작업은 Java 가상 머신에 의해 수행됩니다. 하지만 결국 하위 레이어에 직접 접근하는 것에 비해 자바는 가상 머신 프로세스가 한 단계 더 있기 때문에 이들 네이티브 언어에 비해 성능이 약간 느리다.둘: 기본 관련 기능을 구현하세요
. Java 플랫폼에서 제공하는 표준 클래스 라이브러리와 강력한 API는 대부분의 기능을 완료할 수 있습니다. 그러나 기본 하드웨어를 다루는 일부 기능은 Java API에서 제공하는 클래스 라이브러리에서 완료할 수 없습니다.3: 네이티브 코드를 사용하여 작성된 기존 프로그램과 통합합니다.
c나 c++ 등 자국어로 작성된 소프트웨어를 운영체제에 통합할 때 JNI를 사용할 수 있다.JNI 인터페이스 함수 및 포인터
플랫폼 관련 코드는 JNI 함수를 호출하여 Java 가상 머신 기능에 액세스합니다. JNI 기능은 인터페이스 포인터를 통해 사용할 수 있습니다. 인터페이스 포인터는 포인터 배열을 가리키는 포인터에 대한 포인터이며, 포인터 배열의 각 요소는 인터페이스 함수를 가리킵니다. 각 인터페이스 기능은 배열의 미리 결정된 오프셋에 위치합니다. 다음 그림은 인터페이스 포인터의 구성을 보여줍니다.口 接 JNI 인터페이스의 구성은 C++ 가상 함수 테이블 또는 COM 인터페이스와 유사합니다. 하드 코딩된 함수 테이블 대신 인터페이스 테이블을 사용하면 JNI 네임스페이스를 플랫폼별 코드와 별도로 유지한다는 이점이 있습니다. 가상 머신은 여러 버전의 JNI 함수 테이블을 쉽게 제공할 수 있습니다. 예를 들어, 가상 머신은 다음 두 개의 JNI 함수 테이블을 지원할 수 있습니다.
· 한 테이블은 프로그램 디버깅에 적합한 잘못된 매개변수에 대한 포괄적인 검사를 수행합니다.
· 다른 테이블은 필요한 최소 수준의 검사만 수행합니다. JNI 사양이므로 효율성이 더 높습니다.
JNI 인터페이스 포인터는 현재 스레드에서만 유효합니다. 따라서 기본 메서드는 한 스레드에서 다른 스레드로 인터페이스 포인터를 전달할 수 없습니다. JNI를 구현한 가상 머신은 JNI 인터페이스 포인터가 가리키는 영역에 로컬 스레드 데이터를 할당하고 저장할 수 있습니다.
네이티브 메소드는 JNI 인터페이스 포인터를 매개변수로 허용합니다.
그 중 JNI 구현이 필요한 메소드는 Native 키워드로 선언해야 합니다. 이 클래스에서는 System을 사용합니다. 1oadLibrary() 메소드는 필요한 동적 링크 라이브러리를 로드합니다. 키 코드는 다음과 같습니다.
//Compute.java public class Compute{ public native double sqrt(double params); static{ //调用动态链接库 System.loadLibrary(“compute”); }(2) 바이트 코드로 컴파일됨
(3) 관련 JNI 메소드에 대한 헤더 파일 생성
这个过程的实现一般是通过利用jlavah-jni * class生成的(-jni可以省略),也可以手工生成该文件;但是由于 Java 虚拟机是根据一定的命名规范完成对JNI方法的调用,所以手工编写头文件需要特别小心。
上述文件产生的头文件部分代码如下:
//Compute.h extern“C”{ JNIEXPORT jdoubleJNICALL Java_Compute_comp(JNI-Env *, jobject, jdoubleArray);
JNI函数名称分为三部分:首先是Java关键字,供Java虚拟机识别;然后是调用者类名称(全限定的类名,其中用下划线代替名称分隔符);最后是对应的方法名称,各段名称之间用下划线分割。
JNI函数的参数也由三部分组成:首先是JNIEnv *,是一个指向JNI运行环境的指针;第二个参数随本地方法是静态还是非静态而有所不同一一非静态本地方法的第二个参数是对对象的引用,而静态本地方法的第二个参数是对其Java类的引用;其余的参数对应通常Java方法的参数,参数类型需要根据一定规则进行映射。
(4)编写相应方法的实现代码
在编码过程中,需要注意变量的长度问题,例如Java的整型变量长度为32位,而C语言为16位,所以要仔细核对变量类型映射表,防止在传值过程中出现问题。
(5)将JNI实现代码编译成动态链接库
编译过程是利用C/C++编译器实现的,在windows平台上,编译和连接的结果是动态链接库DLL文件。当要使用生成的动态链接库时,调用者类中需要显式调用该链接库dll文件。
经过上述处理,基本上完成了一个包含本地化方法的Java类的开发。
附录:将Jav类型映射到本地 C 类型
基本类型和本地等效类型 | ||
Java 类型 |
本地类型 |
说明 |
boolean |
jboolean |
无符号,8 位 |
byte |
jbyte |
无符号,8 位 |
char |
jchar |
无符号,16 位 |
short |
jshort |
有符号,16 位 |
int |
jint |
有符号,32 位 |
long |
jlong |
有符号,64 位 |
float |
jfloat |
32 位 |
double |
jdouble |
64 位 |
void |
void |
N/A |
为了使用方便,特提供以下定义。
#define JNI_FALSE 0 #define JNI_TRUE 1
jsize 整数类型用于描述主要指数和大小:
typedef jint jsize;
故障排除
当使用 JNI 从 Java 程序访问本机代码时,您会遇到许多问题。您会遇到的三个最常见的错误是:
1)无法找到动态链接。它所产生的错误消息是:java.lang.UnsatisfiedLinkError。这通常指无法找到共享库,或者无法找到共享库内特定的本机方法。
2)无法找到共享库文件。当用 System.loadLibrary(String libname) 方法(参数是文件名)装入库文件时,请确保文件名拼写正确以及没有指定扩展名。还有,确保库文件的位置在类路径中,从而确保 JVM 可以访问该库文件。
3)无法找到具有指定说明的方法。确保您的 C/C++ 函数实现拥有与头文件中的函数说明相同的说明。
结束语
从 Java 调用 C 或 C++ 本机代码(虽然不简单)是 Java 平台中一种良好集成的功能。虽然 JNI 支持 C 和 C++,但 C++ 接口更清晰一些并且通常比 C 接口更可取。正如您已经看到的,调用 C 或 C++ 本机代码需要赋予函数特殊的名称,并创建共享库文件。当利用现有代码库时,更改代码通常是不可取的。要避免这一点,在 C++ 中,通常创建代理代码或代理类,它们有专门的 JNI 所需的命名函数。然后,这些函数可以调用底层库函数,这些库函数的说明和实现保持不变。
위 내용은 Java 로컬 인터페이스 JNI에서 사용되는 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!