Czy muszę mieć funkcję pomocnika JNI, która wywołuje env-> NewDirectByteBuffer (bufor, rozmiar)?Czy istnieje sposób na utworzenie bezpośredniego obiektu ByteBuffer ze wskaźnika wyłącznie w języku Java?
Odpowiedz
Co mogę zrobić, to stworzyć normalny DirectByteBuffer i zmienić jego adres.
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);
Od tego momentu można uzyskać dostęp do ByteBuffer odwołującego się do adresu bazowego. Zrobiłem to dla dostępu do pamięci na kartach sieciowych dla zerowej kopii i działało dobrze.
Możesz utworzyć DirectByteBuffer dla swojego adresu bezpośrednio, ale jest to bardziej niejasne.
Alternatywą jest użycie niebezpiecznych (ten działa tylko na OpenJDK/HotSpot JVMs w natywnej kolejności bajtów)
Unsafe.getByte(address);
Unsafe.getShort(address);
Unsafe.getInt(address);
Unsafe.getLong(address);
Świetna odpowiedź, jednak musiałem ją zhakować, aby działało, szczególnie Field address = Buffer.class.getDeclaredField ("address"). – Erik
@Erik dziękuję za korektę. –
Oto więc kontynuacja pierwotnego pytania, ponieważ wciąż zwracasz uwagę. Jaki jest najlepszy sposób na wyczyszczenie pamięci dołączonej do ByteBuffer w ten sposób? Czy ByteBuffer sfinalizuje bezpłatny adres, czy powinien zadzwonić internauci i wyczyścić alokację? Dla celów tego pytania załóżmy, że napisałem bibliotekę JNI z owijkami wokół malloc i wolnymi :) Prawdopodobnie zasługuje na to własne pytanie, teraz, gdy myślałem o tym więcej. – Erik
Pan spojrzał na sun.misc.unsafe? Pozwala na bezpośrednią interakcję z pamięcią. – assylias
Zerknąłem i nie widziałem sposobu na utworzenie bezpośredniego bufora bajtowego z sun.misc.unsafe. Znalazłem sposób na stworzenie DirectByteBuffer i to poprzez odbicie. Użyj java.lang.Class.getDeclaredConstructor, aby utworzyć obiekt Constructor, setAccessable na wartość true i wywołaj newInstance z odpowiednimi parametrami. Trochę jane, ale nie musisz pisać kodu JNI. –