2009-07-14 23 views
18

Sto lavorando a un'applicazione Java che deve comunicare con un'applicazione C. L'applicazione C utilizza la memoria condivisa e mmap per comunicare e ho bisogno dell'applicazione Java per accedere alla stessa memoria.Qual è il modo migliore per accedere alla memoria in Java, in modo simile a mmap?

Il mio primo tentativo riguardava l'uso delle chiamate JNI per recuperare i dati dalla memoria condivisa, ma il sovraccarico di ogni chiamata JNI ha causato un calo delle prestazioni, quindi mi piacerebbe un modo per accedere a tale memoria in Java e eseguire il recupero dei dati su il lato Java.

L'idea che ho è che avrei bisogno effettuare le seguenti operazioni:

  1. Utilizzare uno JNI chiamata per ottenere la posizione della locazione di memoria condivisa devo allegare al
  2. Creare un nuovo FileChannel ()
  3. Usa che FileChannel per creare una mappa utilizzando MappedByteBuffer()

E 'questo il modo migliore per farlo? Inoltre, non sono sicuro di come effettivamente creare il FileChannel per puntare alla posizione di memoria corretta.

+0

imho non è possibile, ma mi piace essere corretto – dfa

risposta

11

Cerca su ByteBuffer.allocateDirect. Apparentemente questi buffer possono essere passati sul livello JNI al codice nativo che può accedere direttamente alla memoria.

Vedere this page (indicato di seguito) per suggerimenti.

Ora, non solo il codice JNI può rilevare l'indirizzo dello spazio di memoria nativo all'interno di un buffer creato con ByteBuffer.allocateDirect() sul lato Java, ma può allocare la propria memoria (con malloc(), ad esempio) e quindi richiamare la JVM per avvolgere quello spazio di memoria in un nuovo oggetto ByteBuffer (il metodo JNI per farlo è NewDirectByteBuffer()).

+1

questo sarà il più vicino al metallo come si può ottenere in Java. Sfortunatamente, ByteBuffer avrà ancora bisogno di estrarre informazioni attraverso il limite della VM. Può essere istruttivo dare un'occhiata a come il JDK implementa Deflator - http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/Deflater.html –

+2

Ho finito per usare ByteBuffers e hanno funzionato in modo fantastico. Nel codice JNI, ho creato un ByteBuffer e lo ho restituito al codice Java, che poteva quindi accedere direttamente a quella memoria. Alla fine, le mie applicazioni Java potevano leggere la memoria e scrivere su di essa. Le scritture sarebbero immediatamente visibili a qualsiasi applicazione C/C++ che utilizza la stessa memoria. – Brian

-2

Se si potesse salvare i dati in un file in C e quindi accedere al file da Java, sarebbe meglio. AFAIK non puoi puntare alla memoria nel modo in cui ti piacerebbe usare Java.

+0

Questo è semplicemente sbagliato. I buffer di byte diretti forniscono la capacità desiderata. –

0

Se si possiedono sia l'applicazione C che Java, possono semplicemente comunicare attraverso i flussi della console, ma è brutto per i dati binari ma possibile. Vorrei scambiare la memoria condivisa per uno stile di passaggio più messaggio - ad es. Coppia di socket TCP/IP.

A proposito, che tipo di dati vengono trasmessi e quanto è grande?

+0

Non sono esattamente sicuro della dimensione; potrebbe essere circa 800Mb su un Gb. Sfortunatamente, non ho il lusso di modificare l'applicazione C. – Brian

+0

Creare una nuova applicazione C che avvolge l'applicazione C originale. Una volta fatto, la soluzione di kd304 o la soluzione di AlbertoPL dovrebbero essere possibili. – NamshubWriter

+0

È sempre necessario spostare l'intero dato tra le app? – akarnokd

1

avrei scritto un piccolo modulo C mmaps la memoria condivisa e prese utilizzati per permettere un'altra applicazione per vedere che la memoria (ad esempio, la vostra applicazione Java)

0

Non potresti scrivere una classe Java con alcuni metodi nativi, scrivere l'implementazione del metodo nativo in C per fare ciò che vuoi con mmap. Quindi compila in una libreria nativa e aggiungila al tuo runtime usando LD_LIBRARY_PATH. Ciò consentirà di effettuare chiamate C native in Java senza l'overhead JNI (credo).

Alcuni tutorial qui: link

Per esempio, si potrebbe scrivere una classe Java come ad esempio:

JMMap.java 

public class JMMap { 
    public native void write(...) 
} 

Quindi eseguire javah contro il file di classe per produrre qualcosa di simile:

JMMap.h 

JNIEXPORT void JNICALL Java_JMMap_write(JNIEnv *, jobject); 

Implementalo in un file .c. Compilalo ad una biblioteca. Aggiungilo al percorso LD, quindi chiama semplicemente la funzione Java.

Problemi correlati