Oppure devo avere una funzione helper JNI che chiama env-> NewDirectByteBuffer (buffer, size)?C'è un modo per creare un ByteBuffer diretto da un puntatore esclusivamente in Java?
risposta
Quello che faccio è creare un normale DirectByteBuffer e cambiarne l'indirizzo.
Field address = Buffer.class.getDeclaredField("address");
address.setAccessible(true);
Field capacity = Buffer.class.getDeclaredField("capacity");
capacity.setAccessible(true);
ByteBuffer bb = ByteBuffer.allocateDirect(0).order(ByteOrder.nativeOrder());
address.setLong(bb, addressYouWantToSet);
capacity.setInt(bb, theSizeOf);
Da questo punto è possibile accedere al ByteBuffer riferimento all'indirizzo sottostante. Ho fatto questo per accedere alla memoria su adattatori di rete per la copia zero e ha funzionato bene.
È possibile creare direttamente un DirectByteBuffer per l'indirizzo, ma questo è più oscuro.
Un'alternativa è quella di utilizzare non sicuri (questo funziona solo su OpenJDK/Hotspot JVM e in ordine di byte nativo)
Unsafe.getByte(address);
Unsafe.getShort(address);
Unsafe.getInt(address);
Unsafe.getLong(address);
Ottima risposta, tuttavia ho dovuto lavorarci sopra per farlo funzionare, in particolare Field address = Buffer.class.getDeclaredField ("address"). – Erik
@Erik grazie per la correzione. –
Quindi ecco un seguito alla domanda originale poiché stai ancora prestando attenzione. Qual è il modo migliore per ripulire la memoria collegata al ByteBuffer in questo modo? Il ByteBuffer completerà l'indirizzo gratuito o il chiamante dovrebbe intervenire e ripulire l'allocazione? Ai fini di questa domanda, supponiamo di aver scritto una libreria JNI con wrapper attorno a malloc e gratis :) Probabilmente merita la sua stessa domanda ora che ci ho pensato di più. – Erik
Hai guardato sun.misc.unsafe? Ti permette di interagire direttamente con la memoria. – assylias
Ho dato un'occhiata e non ho visto un modo per creare un buffer di byte diretto con sun.misc.unsafe. Ho trovato un modo per creare un DirectByteBuffer ed è attraverso la riflessione. Utilizzare java.lang.Class.getDeclaredConstructor per creare un oggetto Constructor, setAccessable su true e chiamare newInstance con i parametri appropriati. Piccolo janky ma non devi scrivere alcun codice JNI. –