Heim  >  Artikel  >  Java  >  Detaillierte Erläuterung der von der lokalen Java-Schnittstelle JNI verwendeten Methoden

Detaillierte Erläuterung der von der lokalen Java-Schnittstelle JNI verwendeten Methoden

黄舟
黄舟Original
2017-09-08 10:15:401336Durchsuche

In diesem Artikel werden hauptsächlich relevante Informationen zur Verwendung der lokalen Java-Schnittstelle JNI im Detail vorgestellt. Ich hoffe, dass Sie in diesem Artikel ausführlich auf die JNI-Programmierung zurückgreifen können Verwendung der lokalen Java-Schnittstelle JNI

Für Java-Programmierer glaube ich nicht, dass ich die Vorteile und Vorteile der Java-Sprache erklären muss. Jeder wird Ihnen natürlich viele Dinge erzählen. Aber obwohl wir als Java-Programmierer zugeben müssen, dass die Java-Sprache auch einige eigene Mängel aufweist. Es weist beispielsweise Mängel in Bezug auf die Leistung und den Umgang mit der darunter liegenden Schicht auf. Daher bietet Java einige lokale Schnittstellen. Seine Hauptfunktion besteht darin, eine Standardmethode für die Interaktion von Java-Programmen mit nativem Code über die virtuelle Maschine bereitzustellen. Es ermöglicht Java-Code, der in der Java Virtual Machine (VM) ausgeführt wird, mit Anwendungen und Bibliotheken zusammenzuarbeiten, die in anderen Programmiersprachen wie C, C++ und Assembler geschrieben sind. Der wichtigste Vorteil von JNI besteht darin, dass es der Implementierung der zugrunde liegenden Java Virtual Machine keine Einschränkungen auferlegt. Daher können Anbieter virtueller Java-Maschinen Unterstützung für JNI hinzufügen, ohne andere Teile der virtuellen Maschine zu beeinträchtigen. Programmierer müssen nur eine Version einer nativen Anwendung oder Bibliothek schreiben, die mit allen JNI-fähigen virtuellen Java-Maschinen funktioniert. Werfen wir einen Blick darauf, warum Sie mit nativem Code interagieren sollten:

Erstens: Verbessern Sie die Anwendungsleistung.

Wir wissen, dass Java im Vergleich zu C/C++ und der Assemblersprache relativ „fortgeschritten“ ist. Tatsächlich besteht das Fortgeschrittene hier darin, die Arbeit des Programmierers zu vereinfachen. Viele Dinge auf niedriger Ebene werden von der Java Virtual Machine erledigt. Aber im Vergleich zum direkten Zugriff auf die unterste Ebene verfügt Java über einen weiteren Schritt des Prozesses der virtuellen Maschine, sodass seine Leistung etwas langsamer ist als die dieser nativen Sprachen.

2: Implementieren Sie einige zugrunde liegende Funktionen

. Die von der Java-Plattform bereitgestellte Standardklassenbibliothek und leistungsstarke API können die meisten Funktionen ausführen. Einige Funktionen, die sich mit der zugrunde liegenden Hardware befassen, können jedoch nicht in der von der Java-API bereitgestellten Klassenbibliothek ausgeführt werden.

3: Integration in vorhandene Programme, die mit nativem Code geschrieben wurden.

Bei der Integration von in Muttersprachen wie C oder C++ geschriebener Software in das Betriebssystem kann JNI verwendet werden.

JNI-Schnittstellenfunktionen und -Zeiger

Plattformbezogener Code greift auf Funktionen der Java Virtual Machine zu, indem er JNI-Funktionen aufruft. JNI-Funktionen sind über Schnittstellenzeiger verfügbar. Ein Schnittstellenzeiger ist ein Zeiger auf einen Zeiger, der auf ein Array von Zeigern zeigt, und jedes Element im Array von Zeigern zeigt auf eine Schnittstellenfunktion. Jede Schnittstellenfunktion befindet sich an einem vorgegebenen Offset im Array. Die folgende Abbildung veranschaulicht die Organisation von Schnittstellenzeigern.

                                                                                                                                                                                                                                                        Der Vorteil der Verwendung von Schnittstellentabellen anstelle von hartcodierten Funktionstabellen besteht darin, dass der JNI-Namespace vom plattformspezifischen Code getrennt bleibt. Eine virtuelle Maschine kann problemlos mehrere Versionen einer JNI-Funktionstabelle bereitstellen. Beispielsweise kann die virtuelle Maschine die folgenden zwei JNI-Funktionstabellen unterstützen:

· Eine Tabelle führt eine umfassende Prüfung illegaler Parameter durch und eignet sich zum Debuggen von Programmen

· In der anderen Tabelle werden nur die von der JNI-Spezifikation geforderten Mindestprüfungen durchgeführt, sodass sie effizienter sind.

Der JNI-Schnittstellenzeiger ist nur im aktuellen Thread gültig. Daher können native Methoden keine Schnittstellenzeiger von einem Thread an einen anderen übergeben. Eine virtuelle Maschine, die JNI implementiert, kann lokale Thread-Daten in dem Bereich zuweisen und speichern, auf den der JNI-Schnittstellenzeiger zeigt.

Native Methoden akzeptieren JNI-Schnittstellenzeiger als Parameter.
Wenn die virtuelle Maschine mehrere Aufrufe einer nativen Methode aus demselben Java-Thread ausführt, garantiert sie, dass der an die native Methode übergebene Schnittstellenzeiger derselbe ist. Allerdings kann eine native Methode von verschiedenen Java-Threads aufgerufen werden und daher unterschiedliche JNI-Schnittstellenzeiger akzeptieren.​​​Verwenden Sie in dieser Klasse System. Die Methode 1oadLibrary() lädt die erforderliche dynamische Linkbibliothek. Der Schlüsselcode lautet wie folgt:

(2) Kompiliert in Bytecode

In diesem Prozess aufgrund der Verwendung der nativen Schlüsselwortdeklaration , Java Der Compiler ignoriert Teile von JNI-Methoden, die keinen Codekörper haben.

(3) Generieren Sie Header-Dateien für verwandte JNI-Methoden

    这个过程的实现一般是通过利用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 所需的命名函数。然后,这些函数可以调用底层库函数,这些库函数的说明和实现保持不变。

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der von der lokalen Java-Schnittstelle JNI verwendeten Methoden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn