JNI & Threading



  • Hallo zusammen!

    So ziemlich jeder von uns ist ja mit dem Java-eigenen Konzept zur Integration von native code, z.B. in Form von C-Bibliotheken, JNI vertraut. Oder man hat zumindest schon einmal etwas davon gehört.

    Mich würde nun interessieren, nach welchem grundlegenden Konzept diese Einbindung von native code in eine Java-App stattfindet.
    Warum bin ich daran interessiert?

    Nun ja,
    ich habe im Laufe der Zeit das Monitor-Konzept sowie die Routinen 'wait()' und 'notifyAll()' richtig lieb gewonnen, ;), und möchte daher ungern unter C++ auf eine Bibliothek wie Boost:Threads ausweichen ( dort stehen nicht mal Semaphore zur Verfügung - was unter Java durch ein paar zusätzliche Zeilen Code relativ schnell behoben werden kann! ) Ich möchte also letztendlich Threading-Funktionalitäten meiner Applikationen über Java realisieren, den Systemkern jedoch aus Performance-Gründen nach wie vor mittels C++ realisieren.
    Problem: Durch Java übernommenes Locking müsste somit auch C++-Objekte absichern.
    Die Frage ist jetzt natürlich, ob so etwas überhaupt möglich ist!? Daher wäre es natürlich recht interessant zu erfahren, nach welchem grundlegenden Konzept native Code durch die JRE verwaltet wird.

    Weiss jemand von Euch etwas darüber? (kann auch ganz abstrakt sein!)
    Ist JNI im Rahmen von Threading einsetzbar?

    Danke!

    Grüße,
    TS++



  • OK, Ich nehme mal an, dass C++-Objekte nicht direkt durch Java-gesteuertes Locking geschützt werden können. Aber ein indirekter Schutz vor dem Zugriff durch mehrere in Java erzeugte Threads müsste doch möglich sein!

    Angenommen ich würde mir für eine C++-Klasse mit intern äußerst effizienten Methoden eine Java-Wrapper-Klasse bauen. Also eine Klasse, die dem Programmierer vorgaukelt alle Routinen in Java zu implementieren, die aber in Wirklichkeit mittels JNI, wie mit einer Fernsteuerung, ein C++-Objekt ansteuert. Sichere ich nun von der Java-Seite aus den Zugriff auf diese Wrapper-Klasse ab (ich schreib mir selber ein Semaphore und vielleicht leite ich dann auch noch ein MutexLock ab), so steht doch auch das per Fernsteuerung angesprochene C++-Objekt jeweils nur dem Thread zur Verfügung, der meinetwegen das LockObjekt hält.
    Auf die Art und Weise könnt ich doch per Threading auf der Java-Seite C++-Objekte Thread-sicher machen.(Meine Threads müssen ja von der Java-Seite aus die definierten Wrapper-Klassen verwenden, um mit der C++-Seite meiner Applikation zu kommunizieren.

    Ist mein Lösungsansatz zu trivial oder bin ich auf dem richtigen Weg?
    Ich möchte ja nichts weiter, wie wir eigentlich alle ;), als die Vorteile der Programmiersprachen C++ und Java für meine Eigenentwicklungen zu nutzen und unvorteilhafte Fubktionalitäten auszuklammern. Für die Modellierung von hocheffizienten Datenstrukturen (keine Standarddatencontainer) mit stark technischer Ausrichtung würde ich nach wie vor C bzw. C++ und für alle Netzwerkgeschichten (EJB & Co) und natürlich für das plattformunabhängige Threading würde ich lieber Java verwenden! (Man muss das Rad ja nicht 2X erfinden! ;))

    Grüße,
    TS++


  • Mod

    TS++ schrieb:

    Ich möchte also letztendlich Threading-Funktionalitäten meiner Applikationen über Java realisieren, den Systemkern jedoch aus Performance-Gründen nach wie vor mittels C++ realisieren.

    Ok, ich weiß nicht, was du unter "Systemkern" verstehst, aber wenn es das ist, was ich darunter verstehe, dann ist der eh im Normalfall nicht performancerelevant. Deshalb wäre mein Gegenvorschlag, nahezu alles in Java zu schreiben und nur die wirklich performancekritischen Bereiche in C++ zu schreiben und über JNI einzubinden. In dem Fall wird man es vermutlich leicht hinkriegen können, dass die C++-Teile absolut unkritisch bezüglich Threads sind, auch wenn sie vielleicht parallel verarbeitet werden.


  • Mod

    TS++ schrieb:

    Angenommen ich würde mir für eine C++-Klasse mit intern äußerst effizienten Methoden eine Java-Wrapper-Klasse bauen. Also eine Klasse, die dem Programmierer vorgaukelt alle Routinen in Java zu implementieren, die aber in Wirklichkeit mittels JNI, wie mit einer Fernsteuerung, ein C++-Objekt ansteuert. Sichere ich nun von der Java-Seite aus den Zugriff auf diese Wrapper-Klasse ab (ich schreib mir selber ein Semaphore und vielleicht leite ich dann auch noch ein MutexLock ab), so steht doch auch das per Fernsteuerung angesprochene C++-Objekt jeweils nur dem Thread zur Verfügung, der meinetwegen das LockObjekt hält.
    Auf die Art und Weise könnt ich doch per Threading auf der Java-Seite C++-Objekte Thread-sicher machen.(Meine Threads müssen ja von der Java-Seite aus die definierten Wrapper-Klassen verwenden, um mit der C++-Seite meiner Applikation zu kommunizieren.

    Glaube nicht, dass das so funktioniert. Mit der gleichen Argumentation könntest du ja sagen, dass du dich im C++-Teil nicht mehr um Resourcenfreigabe kümmern mußt, weil der Java-Wrapper ja eh irgendwann vom GC der JVM eingesammelt wird. Das ist aber nicht so. Vielmehr ist es so, dass du, sobal du die JVM durch JNI verläßt, auch nicht mehr die Vorteile der JVM hast.



  • Ich könnte mir vorstellen, dass C++ Funktionen über JNI aufzurufen nicht schneller ist, als das direkt in Java zu coden.
    Davon abgesehen ist Java nicht prinzipiell langsamer als C++, aber das kann jetzt wieder zu einer 10-Seiten Diskussion führen, deshalb möchte ich mich mal darauf beschränken, dass Java-Code IMHO nicht langsamer ist als JNI-Aufrufe.


  • Mod

    Optimizer schrieb:

    Ich könnte mir vorstellen, dass C++ Funktionen über JNI aufzurufen nicht schneller ist, als das direkt in Java zu coden.
    Davon abgesehen ist Java nicht prinzipiell langsamer als C++, aber das kann jetzt wieder zu einer 10-Seiten Diskussion führen, deshalb möchte ich mich mal darauf beschränken, dass Java-Code IMHO nicht langsamer ist als JNI-Aufrufe.

    Ok, dann fache ich die Diskussion mal etwas an:

    3 Punkte:

    1. Es kommt darauf an, wieviel die C++-Funktion macht. Wenn das eine ganz minimale Methode, wie "rundeAb" ist, dann ist der relative JNI-Overhead eindeutig so groß, dass es sich nicht lohnt, die Funktion in C++ zu schreiben. Das würde zu einer Verlangsamung führen.

    2. Wenn man C++ ausgezeichnet kann, dann wird man tatsächlich oft in größeren Methoden, die viel Leistung brauchen, einiges an Performance herausholen können.

    3. Generell muss man bei solchen Fragen messen. Wenn du wissen willst, ob eine bestimmte Methode in einer bestimmten Umgebung lieber in C++ oder lieber in Java implementiert werden sollte, dann schreib beide Versionen und miss nach, welche schneller ist.



  • @Gregor

    Klar kann ich die Vorteile der Virtual Machine nicht in Native Bibliotheken nutzen. Das leuchtet mir mittlerweilen schon ein!
    Nur für den Zugriff auf native code von der Java-Seite aus kann ich doch die VM für meine Zwecke einspannen. Wenn ein unter Java generierter Thread lediglich über eine Wrapper-Klasse die Möglichkeit hat, auf C++-Objekte zuzugreifen und ich diese Wrapper-Klasse über LockObjekte und Semaphore absichere, dann können niemals gleichzeitig zwei von mir auf der Java-Seite generierte Threads unkontrolliert auf die entsprechenden C++-Objekte zugreifen. Ich sichere also nicht die C++-Objekte direkt ab, geht ja wahrscheinlich garnicht, sondern ich sichere per Locking den Zugang zu den C++-Objekten ab.
    Müsste doch eigentlich funktionieren, oder?

    Grüße,
    TS++


  • Mod

    Das hört sich so an, als ob du andauernd über die JNI-Schnittstelle wandern willst. Dazu habe ich ja schon etwas geschrieben (Punkt 1). Du mußt selbst wissen, ob sich das dann noch lohnt. Ohne genauere Angaben kann man dazu nichts sagen. Diesbezüglich empfehle ich dir Punkt 3.



  • @Gregor

    OK, danke!

    Wenn wir mal das Thema Effizienz vielleicht ausklammern, so ergibt sich für uns doch folgendes Problem:
    Java stellt leicht konfigurierbare Strukturen zur Implementierung komplexer Enterprise-Lösungen zur Verfügung. Auch plattformunabhängige Multi-Threaded-Applikationen lassen sich relativ leicht implementieren. Tolle Sache! Gefällt mir im Gegensatz zu diversen C-Bibliotheken sehr gut!
    Leider können nicht alle Probleme mit vorgefertigten Standardstrukturen gelöst werden. Manchmal muss man einfach weiter unten ansetzen. Und genau an dieser Stelle ist Java nicht mehr hilfreich. C++ hingegen stellt für diesen Fall eine Fülle unterschiedlicher Stellschrauben zur Verfügung! (OK, das hat schon so machen in die Arme von Java getrieben! ;))
    Idealerweise müssten jetzt beide Konzepte zusammenarbeiten! Die Frage ist nur wie kriegt man's hin!?

    Grüße,
    TS++



  • Optimizer schrieb:

    Ich könnte mir vorstellen, dass C++ Funktionen über JNI aufzurufen nicht schneller ist, als das direkt in Java zu coden.

    Ich wollte schon seit Ewigkeiten versuchen, eine Mini-3D-"Engine" in Java einmal in Java gecodete Vektoren und Matrizen zu spendieren, und einmal über JNI angebundene C++-Bibliotheken (die ggf. SSE & Co. benutzen), und das zu vergleichen.
    Bin aber nie zu gekommen.

    Wie war das mit Speed nochmal bei unserem Permutations-Problem? 🕶


  • Mod

    Sgt. Nukem schrieb:

    Wie war das mit Speed nochmal bei unserem Permutations-Problem? 🕶

    Die letzte Javaversion war schnellet als die letzte C++ Version, wenn ich mich richtig erinnere. Die hatte aber auch byte statt int verwendet. Das kannst du ja nochmal mit C++ machen und Java damit wieder unterbieten.


Anmelden zum Antworten