ich hab vom shared-mem einer DLL gehört
und auch das man in diesem keine pointer ablegen sollte (oder kann ?) und das die variablen auch vollständig initialisiert sein müssen
meine frage geht jetzt in die richtung : wenn ich die DLL via JNI von java aus anspreche wird ja ein pointer auf die JVM-instanz genutzt -> kann man diesen im shared-mem ablegen um dann von einer zweiten instanz auf diesen zuzugreifen ?
ums auf den punkt zu bringen : es sollen zwei JVMs direkt miteinander kommunizieren ohne den lästigen umweg über memory-mapped files oder sockets
um mal aus der java-sicht zu sprechen : ich möchte gerne das wenn ich in java eine methode calle diese ein objekt durch JNI an die andere JVM-instanz übergibt
also quasi : java-methode -> JNI -> DLL-funktion -> JNI -> java-methode
das halt in der DLL dann auf den jeweils anderen JVM-pointer verwiesen wird
ist das so überhaupt möglich oder bekommt man da probleme weil selbst im shared-mem die pointer ihre gültigkeit verlieren ?
Ich kann mir nicht vorstellen, dass das direkt mit beliebigen Java-Objekten geht. ALLE Java-Objekte liegen unter der Fuchtel der JVM, und sind spezifisch für die JVM-Instanz, und (hoffentlich) von der Außenwelt abgeschottet. Die einzige Ausnahme sind Direct Byte Buffers. Ich könnte mir vorstellen, dass es tatsächlich möglich ist, dass damit zwei JVMs auf denSELBEN Direct Byte Buffer zugreifen… ist aber erstmal ein ziemlich verrückter Gedanke (und dürfte nicht viel bringen, wenn es nicht auf beliebige Objekte anwendbar ist…)
naja, es würde für den anfang schon mal reichen wenn man überhaupt methoden in der anderen instanz callen könnte, und auch wenns am anfang erstmal static ist bis man weis wie man die nötigen objekte der anderen instanz kommt um auch auf instanzen methoden callen zu können
ich hab da schon eher die befürchtung das auf grund der im MSDN genannten beschränkungen der zugriff auf eine andere VM nicht möglich sein wird
man kann es natürlich auch so machen das man z.b. nur zwei instanzen überhaupt verwendet und dann einfach mit settern und gettern arbeitet
so nach dem motto : native(this) -> dll
das man sich dieses java-objekt natürlich nicht in die andere VM holen kann um direkt mit zu arbeiten ist
ich hatte da irgendwie an serialisierung gedacht, weil anders dürfte es ja nicht gehen
Wie gesagt, bei allgemeinen Objekten sehe ich da keine Chance, lasse mich aber gerne eines besseren belehren. Nebenbei aber mal die ganz un-geekige Frage: Wozu das ganze? Also, mit einem konkreten Ziel? Es klingt als würde es darauf rauslaufen, RMI nachzubauen…
es hat zwar jetzt keinen bestimmten anwendungsfall aber mir geht es darum : windows ist mit seinen DLLs modular gebaut, warum soll man das nicht ausnutzen können in dem man ein zentrales modul hat, sich davon mehrere instanzen holen kann, die dann aber trotzdem alle über einen gemeinsamen speicher-bereich verfügen über den man gewisse daten zur runtime unter den instanzen austauschen kann
man könnte es mit einem static in java vergleichen
man nehme eine einfach klasse, deklariere dort ein static field und nutze dies als datenbuffer
nun schreibt man in instanz1 daten dort rein und löst ein event auf instanz2 aus, welche dann die daten des buffers liest und damit was macht
allgemein interessiert mich dieses ganze themengebiet interprocesscommunication, nur will ich halt nicht unbedingt auf dinge wie sockets oder memory-mapped zurück greifen sondern direkt mit der jeweils anderen instanz arbeiten
Also für die Direct Byte Buffers könnte das funktionieren, und ggf. würde ich das vielleicht sogar rein aus Neugier mal probieren, aber eine echte “Kommunikation” (über den reinen Datenaustausch hinaus) wäre damit nicht möglich - also es gäbe z.B. kein Aufrufen von Methoden über JVM-Grenzen hinweg. Und dazu, wie man letzteres ohne RIM & Co erreichen könnte, hätte ich auch keine Idee. Mal schauen, ob jemand anderem dazu noch was einfällt…
public class JNITest
{
public static void callDummy()
{
// ...
}
public static void registerFirst() { registerFirst0(); }
public static void registerSecond() { registerSecond0(); }
public static void callNative() { callNative0(); }
public static native void registerFirst0();
public static native void registerSecond0();
public static native void callNative0();
}```
daraus folgt
```/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class net_bytewelt_forum_unregistriert_JNITest */
#ifndef _Included_net_bytewelt_forum_unregistriert_JNITest
#define _Included_net_bytewelt_forum_unregistriert_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: net_bytewelt_forum_unregistriert_JNITest
* Method: registerFirst0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_net_bytewelt_forum_unregistriert_JNITest_registerFirst0
(JNIEnv *, jclass);
/*
* Class: net_bytewelt_forum_unregistriert_JNITest
* Method: registerSecond0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_net_bytewelt_forum_unregistriert_JNITest_registerSecond0
(JNIEnv *, jclass);
/*
* Class: net_bytewelt_forum_unregistriert_JNITest
* Method: callNative0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_net_bytewelt_forum_unregistriert_JNITest_callNative0
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif```
soweit ich das richtig begriffen habe steht in "JNIEnv *" ein pointer auf das gesamte JNI-system was in jni.h definiert ist
darüber kann man sich mit einer funktion den konkreten "JavaVM"-pointer holen der dann auf die jeweilige VM-instanz zeigt
und dem VM-pointer kann man dann auch aus C wieder Java-methoden finden und callen
meine direkte frage ist jetzt : ist es möglich die VM-pointer in den shared-mem zu packen um darüber dann entsprechend aus instanz "first" callDummy() in instanz "second" zu callen ? oder ist alleine das, auf Grund das man pointer nicht im shared-mem ablegen kann, nicht möglich ?
Mit der Klasse “Unsafe” (welche nicht wirklioch unsafe ist), kann man im nativen Speicher rumpfuschen. Das machen wir bei uns in der Firma um außerhalb von des JVM-Heaps wirklich viel Speicher für Daten zu allokieren. Aber ob man damit über die Prozessgrenze hinweg an Speicher kommt… Keine Ahnung. Müsste ich mal den einen oder anderen hier befragen.
Ja, die Memory Mapped Files wurden ja auch schon in dem Link erwähnt … aber auch im Eröffnungsbeitrag, in der nähe der Aussage „~…möchte ich nicht verwenden“
In bezug auf die Frage " ist es möglich die VM-pointer in den shared-mem zu packen um darüber dann entsprechend aus instanz „first“ callDummy() in instanz „second“ zu callen ?" hätte ich jetzt nur schreiben können: Ausprobieren! Ich schätze dass, FALLS es geht, es ein paar Stolpersteine geben könnte. Der JVM-Pointer ist recht mächtig, man kann sich davon das JNIEnv holen und theoretisch beliebigen Mist machen… Vielleicht probier’ ich das auch mal, aber mangels konkreter Anwendungsfälle liegt es ziemlich weit unten in meiner „Das müßte ich mal ausprobieren“-Queue…
das mit dem “einfach mal ausprobieren” ist ja nicht weiter das problem, alles nötige wird man sich sicherlich irgendwo aus dem netz zusammen klicken können, allerdings hätte ich auf grund mangelnder C-kenntnisse probleme die stolpersteine auszuräumen, im gegensatz zu java wo ich die compiler-meldungen verstehe
ich werd mal ausprobieren ob ich die woche über irgendwas zusammenkopiert bekomme was dann auch letztendlich gelinkt werden kann, ob es dann wirklich funktioniert und was man noch alles dran rumbasteln muss damit es “halbwegs sauber” wird werden wir sehen
ums auf den punkt zu bringen : es sollen zwei JVMs direkt miteinander kommunizieren ohne den lästigen umweg über memory-mapped files oder sockets
Wenn es „einfach“ wäre, würde jeder das auch nutzen und nicht den Umweg nehmen oder ?
Generell:
moderne OS schotten den Stack und den Heap/Freestore von programmen (sprich: Prozessen) untereinander ab.
Weiterhin mappen sie Speicheradressen, d.h. du bekommst die reale physikalische vom Betriebssystem gar nicht zu gesicht … theorethisch.
Das heisst, adresse 0x000000ff kann in 2 unterschiedlichen prozessen gleichzeitig benutzt werden, und jedesmal liegen andere daten da drunter.
Windows bietet einige Möglichkeiten, was zu machen was aussieht als wuerden 2 prozesse den gleichen Speicherbereich verwenden …
aber entweder sinds readonly dinge (du kannst die code und readonly breiche von dlls an bestimmte einsprungsadressen nageln) oder es wird unten drunter doch wieder IPC gemacht.
es gibt funktionen, wo man in den speicher anderer prozesse schauen kann … aber 1. brauchst dazu entsprechende Rechte, und 2. wird der speicher zu dir in einen vorgegebenen adressbereich kopiert und snchronisiert (mapping).
memory-mapped files sind schon der einfachste und sinmpelste weg.
Selbst wenn du auf den speicher ner anderen app zugreifen koenntest, würdes das genau so ähnlich programmieren wie MMIO
und MMIO geht auch mit ner virtuellen datei …
Vorteil, du brauchst weniger rechte … das ganze passiert in abgeschlossenen Speicherbereichen, und das kopieren und sunchronisieren (sprich mappen) im Hintergrund uebernimmt dir das OS soweiso …
einzig die verwaltung des MMIO (erzeugen, freigeben) musst machen, aber das einzusparen ist niemals nen grund fuer irgendwelche schmutzigen Hacks ^^