JNA scheint im Vergleich zu JNI ein bisschen einfacher zu verwenden zu sein, um nativen Code aufzurufen. In welchen Fällen würden Sie JNI über JNA verwenden?
java
java-native-interface
native
jna
Marcus Leon
quelle
quelle
Antworten:
Dies sind die Probleme, auf die ich gestoßen bin. Vielleicht gibt es noch mehr. Aber im Allgemeinen unterscheidet sich die Leistung nicht so stark zwischen jna und jni. Wo immer Sie JNA verwenden können, verwenden Sie es.
BEARBEITEN
Diese Antwort scheint sehr beliebt zu sein. Hier sind einige Ergänzungen:
Daher glaube ich immer noch, dass es nach Möglichkeit besser ist, JNA oder BridJ zu verwenden und zu jni zurückzukehren, wenn die Leistung kritisch ist, denn wenn Sie häufig native Funktionen aufrufen müssen, ist ein Leistungseinbruch spürbar.
quelle
JNIEXPORT
Funktionen aufrufen . Ich untersuche derzeit JavaCpp als Option, die JNI verwendet, aber ich glaube nicht, dass Vanilla JNI dies unterstützt. Gibt es eine Möglichkeit, C ++ - Mitgliedsfunktionen mit Vanilla JNI aufzurufen, die ich übersehen habe?Es ist schwierig, eine so allgemeine Frage zu beantworten. Ich nehme an, der offensichtlichste Unterschied besteht darin, dass mit JNI die Typkonvertierung auf der nativen Seite der Java / Native-Grenze implementiert wird, während mit JNA die Typkonvertierung in Java implementiert wird. Wenn Sie sich mit dem Programmieren in C bereits recht wohl fühlen und selbst nativen Code implementieren müssen, würde ich davon ausgehen, dass JNI nicht zu komplex erscheint. Wenn Sie ein Java-Programmierer sind und nur eine native Bibliothek eines Drittanbieters aufrufen müssen, ist die Verwendung von JNA wahrscheinlich der einfachste Weg, um die möglicherweise nicht so offensichtlichen Probleme mit JNI zu vermeiden.
Obwohl ich noch nie Unterschiede gemessen habe, würde ich aufgrund des Designs zumindest annehmen, dass die Typkonvertierung mit JNA in einigen Situationen schlechter abschneidet als mit JNI. Wenn Sie beispielsweise Arrays übergeben, konvertiert JNA diese zu Beginn jedes Funktionsaufrufs von Java in native und am Ende des Funktionsaufrufs zurück. Mit JNI können Sie selbst steuern, wann eine native "Ansicht" des Arrays generiert wird. Möglicherweise wird nur eine Ansicht eines Teils des Arrays erstellt, die Ansicht über mehrere Funktionsaufrufe hinweg beibehalten und am Ende die Ansicht freigegeben und entschieden, ob Sie möchten um die Änderungen beizubehalten (möglicherweise müssen die Daten zurückkopiert werden) oder die Änderungen zu verwerfen (keine Kopie erforderlich). Ich weiß, dass Sie ein natives Array für Funktionsaufrufe mit JNA mithilfe der Speicherklasse verwenden können, dies erfordert jedoch auch das Kopieren des Speichers. Dies kann bei JNI unnötig sein. Der Unterschied ist möglicherweise nicht relevant, aber wenn Ihr ursprüngliches Ziel darin besteht, die Anwendungsleistung durch Implementierung von Teilen davon in nativem Code zu steigern, scheint die Verwendung einer Bridge-Technologie mit schlechterer Leistung nicht die naheliegendste Wahl zu sein.
quelle
Das ist nur das, was ich mir auf den ersten Blick einfallen lassen kann, obwohl ich auch kein schwerer Benutzer bin. Es scheint auch so, als könnten Sie JNA vermeiden, wenn Sie eine bessere Benutzeroberfläche als die von ihnen bereitgestellte wünschen, aber Sie könnten dies in Java umgehen.
quelle
Übrigens haben wir in einem unserer Projekte einen sehr kleinen JNI-Fußabdruck beibehalten. Wir haben Protokollpuffer zur Darstellung unserer Domänenobjekte verwendet und hatten daher nur eine native Funktion, um Java und C zu überbrücken (dann würde diese C-Funktion natürlich eine Reihe anderer Funktionen aufrufen).
quelle
Es ist keine direkte Antwort und ich habe keine Erfahrung mit JNA, aber wenn ich mir die Projekte mit JNA anschaue ansehe und Namen wie SVNKit, IntelliJ IDEA, NetBeans IDE usw. sehe, glaube ich eher, dass es eine ziemlich anständige Bibliothek ist.
Eigentlich denke ich definitiv, dass ich JNA anstelle von JNI verwendet hätte, als ich musste, da es in der Tat einfacher aussieht als JNI (das einen langweiligen Entwicklungsprozess hat). Schade, JNA wurde zu diesem Zeitpunkt noch nicht veröffentlicht.
quelle
Wenn Sie die JNI-Leistung wünschen, sich aber von ihrer Komplexität abschrecken lassen, können Sie Tools verwenden, die automatisch JNI-Bindungen generieren. Mit JANET (Haftungsausschluss: Ich habe es geschrieben) können Sie beispielsweise Java- und C ++ - Code in einer einzigen Quelldatei mischen und z. B. mit der Standard-Java-Syntax Aufrufe von C ++ nach Java tätigen. So drucken Sie beispielsweise eine C-Zeichenfolge in die Java-Standardausgabe:
JANET übersetzt dann das in Backticks eingebettete Java in die entsprechenden JNI-Aufrufe.
quelle
Ich habe tatsächlich einige einfache Benchmarks mit JNI und JNA durchgeführt.
Wie andere bereits betont haben, dient JNA der Bequemlichkeit. Sie müssen keinen nativen Code kompilieren oder schreiben, wenn Sie JNA verwenden. Der native Bibliothekslader von JNA ist auch einer der besten / am einfachsten zu verwendenden, die ich je gesehen habe. Leider können Sie es anscheinend nicht für JNI verwenden. (Deshalb habe ich eine Alternative für System.loadLibrary () geschrieben.) , die die von JNA verwendet und das nahtlose Laden aus dem Klassenpfad (dh Jars) unterstützt.)
Die Leistung von JNA kann jedoch viel schlechter sein als die von JNI. Ich habe einen sehr einfachen Test durchgeführt, der eine einfache native Ganzzahl-Inkrementfunktion "return arg + 1;" nannte. Mit jmh durchgeführte Benchmarks zeigten, dass JNI-Aufrufe dieser Funktion 15-mal schneller sind als JNA.
Ein "komplexeres" Beispiel, bei dem die native Funktion ein ganzzahliges Array von 4 Werten zusammenfasst, zeigte immer noch, dass die JNI-Leistung dreimal schneller ist als die von JNA. Der reduzierte Vorteil war wahrscheinlich darauf zurückzuführen, wie Sie in JNI auf Arrays zugreifen: In meinem Beispiel wurden einige Elemente erstellt und bei jedem Summierungsvorgang erneut freigegeben.
Code und Testergebnisse finden Sie bei github .
quelle
Ich habe JNI und JNA zum Leistungsvergleich untersucht, weil wir uns für einen von ihnen entscheiden mussten, um eine DLL im Projekt aufzurufen, und wir hatten eine Echtzeitbeschränkung. Die Ergebnisse haben gezeigt, dass JNI eine höhere Leistung als JNA aufweist (ungefähr 40-mal). Vielleicht gibt es einen Trick für eine bessere Leistung in JNA, aber für ein einfaches Beispiel ist er sehr langsam.
quelle
Ist der Hauptunterschied zwischen JNA und JNI nicht, dass Sie mit JNA keinen Java-Code aus nativem (C) Code aufrufen können, es sei denn, ich vermisse etwas?
quelle
In meiner spezifischen Anwendung erwies sich JNI als weitaus einfacher zu verwenden. Ich musste fortlaufende Streams zu und von einer seriellen Schnittstelle lesen und schreiben - und sonst nichts. Anstatt zu versuchen, die sehr komplexe Infrastruktur in JNA zu erlernen, fand ich es viel einfacher, die native Benutzeroberfläche in Windows mit einer speziellen DLL zu prototypisieren, die nur sechs Funktionen exportierte:
quelle