Maison  >  Article  >  Java  >  Explication détaillée des méthodes utilisées par l'interface locale Java JNI

Explication détaillée des méthodes utilisées par l'interface locale Java JNI

黄舟
黄舟original
2017-09-08 10:15:401290parcourir

Cet article présente principalement des informations pertinentes sur la façon d'utiliser l'interface locale Java JNI en détail. J'espère que grâce à cet article, vous pourrez utiliser à fond la programmation JNI. Les amis dans le besoin pourront se référer à

Explication détaillée. de l'interface locale Java JNI Comment utiliser

Pour les programmeurs Java, je ne pense pas avoir besoin d'expliquer les avantages et les avantages du langage Java. Tout le monde vous dira naturellement beaucoup de choses. Mais même si nous, en tant que programmeurs Java, devons admettre que le langage Java présente également ses propres défauts. Par exemple, il présente des défauts en termes de performances et de gestion de la couche sous-jacente. Par conséquent, Java fournit des interfaces locales. Sa fonction principale est de fournir un moyen standard aux programmes Java d'interagir avec le code natif via la machine virtuelle. C'est ce que nous appelons habituellement l'interface native Java (JNI - Java Native Interface). Il permet au code Java exécuté dans la machine virtuelle (VM) Java d'interagir avec des applications et des bibliothèques écrites dans d'autres langages de programmation tels que C, C++ et le langage assembleur. L'avantage le plus important de JNI est qu'il n'impose aucune restriction sur l'implémentation de la machine virtuelle Java sous-jacente. Par conséquent, les fournisseurs de machines virtuelles Java peuvent ajouter la prise en charge de JNI sans affecter les autres parties de la machine virtuelle. Les programmeurs n'ont besoin d'écrire qu'une seule version d'une application ou d'une bibliothèque native qui fonctionnera avec toutes les machines virtuelles Java compatibles JNI. Voyons pourquoi vous devriez interagir avec le code natif :

Premièrement : améliorer les performances des applications. Nous savons que Java est relativement "avancé" par rapport au c/c++ et au langage assembleur. En fait, l'avancé ici est de simplifier le travail du programmeur. De nombreuses tâches de bas niveau sont effectuées par la machine virtuelle Java. Mais après tout, par rapport à l'accès direct à la couche inférieure, Java comporte une étape supplémentaire dans le processus de la machine virtuelle, ses performances sont donc légèrement plus lentes que celles de ces langages natifs.

2 : Implémenter certaines fonctions liées au sous-jacent . La bibliothèque de classes standard et la puissante API fournies par la plateforme Java peuvent compléter la plupart des fonctions. Cependant, certaines fonctions liées au matériel sous-jacent ne peuvent pas être exécutées dans la bibliothèque de classes fournie par l'API Java.

3 : Intégrez des programmes existants écrits en code natif. Lors de l'intégration de logiciels écrits dans des langages natifs tels que c ou c++ sur le système d'exploitation, JNI peut être utilisé.

Fonctions et pointeurs de l'interface JNI

Le code lié à la plate-forme accède aux fonctions de la machine virtuelle Java en appelant les fonctions JNI. Les fonctions JNI sont disponibles via des pointeurs d'interface. Un pointeur d'interface est un pointeur vers un pointeur, qui pointe vers un tableau de pointeurs, et chaque élément du tableau de pointeurs pointe vers une fonction d'interface. Chaque fonction d'interface est située à un décalage prédéterminé dans le réseau. La figure suivante illustre l'organisation des pointeurs d'interface.

                                                                                                                                                                                                                                                       L'avantage d'utiliser des tables d'interface au lieu de tables de fonctions codées en dur est de séparer l'espace de noms JNI du code spécifique à la plate-forme. Une machine virtuelle peut facilement fournir plusieurs versions d'une table de fonctions JNI. Par exemple, la machine virtuelle peut prendre en charge les deux tables de fonctions JNI suivantes :

· Une table effectue une vérification complète des paramètres illégaux et convient au débogage des programmes ; L'autre table Seul le niveau minimum de vérifications requis par la spécification JNI est effectué, il est donc plus efficace.

Le pointeur d'interface JNI n'est valide que dans le fil de discussion actuel. Par conséquent, les méthodes natives ne peuvent pas transmettre de pointeurs d’interface d’un thread à un autre. Une machine virtuelle qui implémente JNI peut allouer et stocker des données de thread local dans la zone pointée par le pointeur d'interface JNI.

Les méthodes natives acceptent les pointeurs d'interface JNI comme paramètres.
Lorsque la machine virtuelle effectue plusieurs appels à une méthode native à partir du même thread Java, elle garantit que le pointeur d'interface passé à la méthode native est le même. Cependant, une méthode native peut être appelée par différents threads Java et peut donc accepter différents pointeurs d'interface JNI.​​​Dans cette classe, utilisez System. La méthode 1loadLibrary() charge la bibliothèque de liens dynamiques requise. Le code clé est le suivant :

(2) Compilé en code octet

Dans ce processus, en raison de l'utilisation d'une déclaration de mot clé native , Java Le compilateur ignore les parties des méthodes JNI qui n'ont pas de corps de code.

(3) Générer des fichiers d'en-tête pour les méthodes JNI associées

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn