119 votes

Utiliser JNI au lieu de JNA pour appeler du code natif ?

JNA semble un peu plus facile à utiliser pour appeler du code natif que JNI. Dans quels cas utiliseriez-vous JNI plutôt que JNA ?

0 votes

Un facteur important pour lequel nous avons choisi JNA plutôt que JNI, est que JNA ne nécessite aucune modification de nos bibliothèques natives. Le fait de devoir personnaliser les bibliothèques natives juste pour pouvoir travailler avec Java était un grand NON pour nous.

128voto

Denis Tulskiy Points 10444
  1. JNA ne prend pas en charge le mappage des classes c++, donc si vous utilisez la bibliothèque c++, vous aurez besoin d'un wrapper JNA.
  2. Si vous avez besoin de beaucoup de copies de mémoire. Par exemple, vous appelez une méthode qui vous renvoie un grand tampon d'octets, vous modifiez quelque chose dans celui-ci, puis vous devez appeler une autre méthode qui utilise ce tampon d'octets. Cela vous obligerait à copier ce tampon de c à java, puis à le recopier de java à c. Dans ce cas, jni gagnera en performance car vous pouvez conserver et modifier ce tampon en c, sans le copier.

Voici les problèmes que j'ai rencontrés. Il y en a peut-être d'autres. Mais en général, les performances ne sont pas si différentes entre jna et jni, donc si vous pouvez utiliser JNA, utilisez-le.

EDIT

Cette réponse semble être assez populaire. Voici donc quelques ajouts :

  1. Si vous avez besoin de mapper C++ ou COM, il existe une bibliothèque d'Oliver Chafic, créateur de JNAerator, appelée BridJ . Il s'agit d'une bibliothèque encore jeune, mais elle présente de nombreuses caractéristiques intéressantes :
    • Interopérabilité dynamique C / C++ / COM : appelez des méthodes C++, créez des objets C++ (et sous-classez des classes C++ depuis Java !).
    • Correspondances de types simples avec une bonne utilisation des génériques (y compris un modèle beaucoup plus agréable pour les pointeurs).
    • Support complet de JNAerator
    • fonctionne sur Windows, Linux, MacOS X, Solaris, Android
  2. En ce qui concerne la copie de mémoire, je crois que JNA supporte les ByteBuffers directs, ce qui permet d'éviter la copie de mémoire.

Ainsi, je continue de penser que, dans la mesure du possible, il est préférable d'utiliser JNA ou BridJ, et de revenir à jni si les performances sont critiques, car si vous devez appeler fréquemment des fonctions natives, la baisse des performances est sensible.

6 votes

Je ne suis pas d'accord, la JNA a beaucoup de frais généraux. Bien que sa commodité vaille la peine d'être utilisée dans du code non critique en termes de temps.

3 votes

Je vous conseille de faire preuve de prudence avant d'utiliser BridJ pour un projet Android. page de téléchargement : " BridJ fonctionne partiellement sur les émulateurs Android/arm (avec le SDK), et probablement même sur des appareils réels (non testés). "

0 votes

J'utilise jna et comme denis l'a dit, j'appelle une méthode qui me renvoie un grand tampon de données d'une image à partir d'un périphérique usb. Mais dans mon cas, la méthode dépend d'un appareil photo externe, donc jusqu'à ce que quelqu'un ne capture pas l'image, elle doit attendre dans cette dll. En général, cela fonctionne bien, mais dans beaucoup d'autres ordinateurs que le mien, il retourne automatiquement de la méthode en prenant des données vierges sans même attendre une seconde. J'ai rencontré ce problème sur des ordinateurs plus anciens et sur ceux qui sont équipés d'une prise USB 3.0. Alors est-ce un problème de jna ?

31voto

jarnbjo Points 18238

Il est difficile de répondre à une question aussi générique. Je suppose que la différence la plus évidente est qu'avec JNI, la conversion de type est implémentée du côté natif de la frontière Java/natif, alors qu'avec JNA, la conversion de type est implémentée en Java. Si vous êtes déjà à l'aise avec la programmation en C et que vous devez implémenter vous-même du code natif, je suppose que JNI ne vous semblera pas trop complexe. Si vous êtes un programmeur Java et que vous avez seulement besoin d'invoquer une bibliothèque native tierce, l'utilisation de JNA est probablement la voie la plus facile pour éviter les problèmes peut-être pas si évidents de JNI.

Bien que je n'aie jamais évalué les différences, je suppose, du fait de la conception, que la conversion de type avec JNA sera, dans certaines situations, moins performante qu'avec JNI. Par exemple, lors du passage de tableaux, JNA les convertira de Java en natif au début de chaque appel de fonction et inversement à la fin de l'appel de fonction. Avec JNI, vous pouvez contrôler vous-même le moment où une "vue" native du tableau est générée, en ne créant potentiellement qu'une vue d'une partie du tableau, en conservant la vue sur plusieurs appels de fonction et, à la fin, en libérant la vue et en décidant si vous voulez conserver les changements (ce qui peut nécessiter de recopier les données) ou rejeter les changements (aucune copie nécessaire). Je sais que vous pouvez utiliser un tableau natif à travers des appels de fonction avec JNA en utilisant la classe Memory, mais cela nécessitera également une copie de la mémoire, ce qui peut être inutile avec JNI. La différence peut ne pas être pertinente, mais si votre objectif initial est d'augmenter les performances de l'application en implémentant des parties de celle-ci en code natif, l'utilisation d'une technologie de pont moins performante ne semble pas être le choix le plus évident.

8voto

stonemetal Points 4734
  1. Vous écrivez du code il y a quelques années, avant l'existence de JNA, ou vous ciblez un JRE antérieur à la version 1.4.
  2. Le code avec lequel vous travaillez n'est pas dans une DLL. \SO.
  3. Vous travaillez sur du code qui est incompatible avec la LGPL.

C'est seulement ce que je peux trouver dans ma tête, bien que je ne sois pas un grand utilisateur de l'un ou l'autre. Il semble également que vous pourriez éviter JNA si vous vouliez une meilleure interface que celle qu'ils fournissent, mais vous pourriez coder autour de cela en Java.

9 votes

Je ne suis pas d'accord avec le point 2 : convertir une librairie statique en librairie dynamique est facile. Voir ma question à ce sujet stackoverflow.com/questions/845183/

3 votes

À partir de JNA 4.0, JNA est sous double licence, LGPL 2.1 et Apache 2.0, et c'est à vous de choisir la licence qui vous convient.

8voto

Ustaman Sangat Points 757

À propos, dans l'un de nos projets, nous avons gardé une très petite empreinte JNI. Nous utilisions des tampons de protocole pour représenter nos objets de domaine et n'avions donc qu'une seule fonction native pour faire le lien entre Java et C (bien entendu, cette fonction C appelait ensuite un tas d'autres fonctions).

5 votes

Donc, au lieu d'un appel de méthode, nous avons le passage de message. J'ai investi pas mal de temps dans JNI et JNA et aussi BridJ, mais très vite, ils deviennent tous un peu trop effrayants.

6voto

Pascal Thivent Points 295221

Ce n'est pas une réponse directe et je n'ai pas d'expérience avec la JNA mais, quand je regarde le Projets utilisant JNA et voir des noms comme SVNKit, IntelliJ IDEA, NetBeans IDE, etc., j'ai tendance à croire qu'il s'agit d'une bibliothèque plutôt décente.

En fait, je pense vraiment que j'aurais utilisé JNA au lieu de JNI quand j'ai dû le faire, car il semble effectivement plus simple que JNI (dont le processus de développement est ennuyeux). Dommage que JNA n'ait pas été publié à cette époque.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X