Question

JNA semble un peu juste plus facile à utiliser pour appeler du code natif par rapport à JNI. Dans quels cas utiliseriez-vous JNI sur la JNA?

Était-ce utile?

La solution

  1. JNA ne prend pas en charge la cartographie de classes C ++, donc si vous utilisez c ++ bibliothèque, vous aurez besoin d'une enveloppe de JNI
  2. Si vous avez besoin beaucoup de copie de mémoire. Par exemple, vous appelez une méthode qui vous renvoie un grand tampon d'octets, vous changez quelque chose, alors vous devez appeler une autre méthode qui utilise ce tampon d'octets. Cela vous demandera de copier ce tampon de C à Java, puis copiez-le retour de java à c. Dans ce cas JNI gagnera en performance, car vous pouvez conserver et modifier ce tampon en c, sans copier.

Ce sont les problèmes que j'ai rencontrés. Peut-être il y a plus. Mais la performance générale est pas différente entre jna et JNI, donc où vous pouvez utiliser la JNA, l'utiliser.

EDIT

Cette réponse semble être très populaire. Alors, voici quelques ajouts:

  1. Si vous avez besoin de la carte C ++ ou COM, il y a une bibliothèque par Oliver Chafic, créateur de JNAerator, appelé BridJ . Il est encore une jeune bibliothèque, mais il possède de nombreuses fonctionnalités intéressantes:
    • dynamique C / C ++ / COM Interop: (! Et les classes sous-classe C ++ de Java) appeler les méthodes C de, créer des objets C ++
    • des correspondances de type simple, avec une bonne utilisation des médicaments génériques (y compris le modèle beaucoup plus agréable pour les Pointers)
    • Support complet JNAerator
    • fonctionne sous Windows, Linux, Mac OS X, Solaris, Android
  2. En ce qui concerne la copie de la mémoire, je crois que la JNA soutient ByteBuffers directe pour que la copie de mémoire peut être évitée.

Alors, je crois toujours que la mesure du possible, il est préférable d'utiliser la JNA ou BridJ, et revenir à JNI si la performance est critique, parce que si vous avez besoin d'appeler des fonctions natives fréquemment, perte de performance est notable.

Autres conseils

Il est difficile de répondre à cette question générique. Je suppose que la différence la plus évidente est que, avec JNI, la conversion de type est mis en œuvre sur le côté natif de la frontière Java / natif, alors qu'avec la JNA, la conversion de type est implémenté en Java. Si vous vous sentez déjà tout à fait à l'aise avec la programmation en C et doivent mettre en œuvre un code natif vous, je suppose que JNI ne semblera pas trop complexe. Si vous êtes un programmeur Java et seulement besoin d'appeler une bibliothèque native tiers, à l'aide de la JNA est probablement le chemin le plus facile d'éviter les problèmes peut-être pas si évident avec JNI.

Bien que je ne l'ai jamais benchmarkée aucune différence, je cause de la conception, au moins supposer que la conversion de type avec la JNA dans certaines situations se produira pire que avec JNI. Par exemple, lorsque des tableaux de passage, la JNA va convertir à partir de Java natif au début de chaque appel de fonction et de retour à la fin de l'appel de fonction. Avec JNI, vous pouvez vous contrôler quand une « vue » native du tableau est généré, ce qui peut créer seulement une vue d'une partie du tableau, gardez la vue sur plusieurs appels de fonction et à la sortie de fin de la vue et de décider si vous voulez pour conserver les modifications (qui pourraient nécessiter de copier le dos de données) ou annuler les modifications (pas de copie nécessaire). Je sais que vous pouvez utiliser un tableau natif à travers des appels de fonction avec la JNA en utilisant la classe de mémoire, mais cela va aussi exiger la copie de la mémoire, qui peut être inutile avec JNI. La différence ne peut être pertinente, mais si votre objectif initial est d'augmenter les performances des applications en mettant en œuvre des parties dans le code natif, en utilisant une technologie de pont pire performant ne semble pas être le choix le plus évident.

  1. Vous écrivez du code il y a quelques années avant qu'il y ait de la JNA ou ciblez un avant 1,4 JRE.
  2. Le code que vous travaillez avec est pas dans une DLL \ SO.
  3. Vous travaillez sur le code qui est incompatible avec LGPL.

C'est seulement ce que je peux venir avec du haut de ma tête, mais je ne suis pas un gros utilisateur soit. Il semble aussi que vous pourriez éviter la JNA si vous vouliez une meilleure interface que celle qu'ils fournissent, mais vous pouvez coder autour de ce en java.

Par ailleurs, dans l'un de nos projets, nous avons conservé une empreinte très petite JNI. Nous avions des tampons de protocole pour représenter nos objets de domaine et a donc une seule fonction native de pont Java et C (alors bien sûr que la fonction C appellerait un tas d'autres fonctions).

Il est pas une réponse directe et je n'ai pas d'expérience avec la JNA mais, quand je regarde les projets utilisant JNA et voir des noms comme SVNKit, IntelliJ IDEA, NetBeans IDE, etc, je suis tendance à croire qu'il est une bibliothèque assez décent.

En fait, je pense vraiment que je l'aurais utilisé au lieu de la JNA JNI quand je devais comme il semble bien plus simple que JNI (qui a un processus de développement ennuyeux). Dommage, la JNA n'a pas été publié à ce moment.

Si vous voulez des performances JNI, mais sont intimidés par sa complexité, vous pouvez envisager d'utiliser des outils qui génèrent des liaisons JNI automatiquement. Par exemple, JANET (disclaimer: je l'ai écrit) vous permet de mélanger Java et du code C ++ en un seul fichier source, et par exemple faire des appels de C ++ à Java en utilisant la syntaxe Java standard. Par exemple, voici comment vous imprimer une chaîne de C à la sortie standard Java:

native "C++" void printHello() {
    const char* helloWorld = "Hello, World!";
    `System.out.println(#$(helloWorld));`
}

JANET se traduit alors le Java intégré backtick-dans les appels JNI approprié.

En fait, je l'ai fait quelques repères simples avec JNI et la JNA.

Comme d'autres déjà souligné, la JNA est pour plus de commodité. Vous n'avez pas besoin de compiler ou d'écrire du code natif lors de l'utilisation de la JNA. chargeur de bibliothèque native de la JNA est également l'un des meilleurs / plus facile à utiliser que j'ai jamais vu. Malheureusement, vous ne pouvez pas l'utiliser pour JNI il semble. (Voilà pourquoi je l'ai écrit à github .

J'enquêté sur JNI et la JNA pour la comparaison des performances parce que nous avions besoin de décider un d'entre eux d'appeler un dll dans le projet et nous avons eu une contrainte de temps réel. Les résultats ont montré que JNI a une plus grande performance que JNA (environ 40 fois). Peut-être il y a un truc pour une meilleure performance dans la JNA, mais il est très lent pour un exemple simple.

À moins que je me manque quelque chose, n'est pas la principale différence entre la JNA vs JNI que, avec la JNA, vous ne pouvez pas appeler du code Java à partir du code natif (C)?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top