2013-07-16 15 views
13

W Javie pamięć przydzielona przez bufory nio jest zwalniana za pomocą instancji sun.misc.Cleaner, niektórych specjalnych odwołań fantomowych, które są bardziej wydajne niż finalizacja obiektu.Bezpośrednia pamięć Java: używanie sun.misc.Cleaner w niestandardowych klasach

Czy ten czystszy mechanizm został zakodowany na stałe w JVM tylko dla podklas bezpośrednich buforów, czy też można użyć czyszczących w komponentach niestandardowych (na przykład, pisząc niestandardowy bufor bezpośredniego bajtu)?

Tutaj nie mówię o odzyskaniu czystszego pola istniejącego bufora bezpośredniego nio. Nie mówię też o ręcznym zwalnianiu pamięci. Chodzi o napisanie nowej klasy, która przydziela pamięć bezpośrednią i czyści ją sprawnie i automatycznie przez mechanizm odśmiecania.

+2

Nie powinieneś używać niczego w sun.misc. * Dla czegokolwiek, a dokumentacja JDK już tak mówi. – EJP

+11

Wiem, a także nie powinienem palić;) Dobrze, że autorzy bibliotek o wysokiej wydajności opartych na sun.misc.Unsafe pominęli tę regułę. –

+3

Antoine, można tego uniknąć. Tylko sun.misc.Cleaner przetrwa, spojrzy na JEP 260 i przetestuje swój kod z Javą 1.9, zobaczysz co mamy na myśli. Mój pomocnik deallocator obsługuje Javę 1.9 i nie używa klas sun.misc z wyjątkiem sun.misc.Cleaner. – gouessej

Odpowiedz

14

Po spędzeniu więcej czasu na czytanie doc API (http://docs.oracle.com/javase/7/docs/api/java/lang/ref/package-summary.html) Myślę, że mam bardziej szczegółową odpowiedź:

1) jest możliwe ponowne sun.misc.Cleaner wykonać efektywne oczyszczanie własnych klas niestandardowych . Zadeklarować odkurzacza poprzez wywołanie przewidzianej metody fabryki:

sun.misc.Cleaner.create(Object ob, Runnable cleanup); 

Od jakiegoś czasu nie mogę zmusić go do prawidłowej pracy, to dlatego, że był na tyle kretyński do zdefiniowania runnable kod oczyszczanie mój odkurzacz jako anonimowy klasy, który zachował (silne) odniesienie do mojego obiektu odniesienia, uniemożliwiając mu bycie "fantomowym osiągalnym" ...

2) Nie ma innego sposobu na wdrożenie tak skutecznego czyszczenia (nawet przy pomocy fantomowych odniesień)

Rzeczywiście wątek obsługi odwołania obsługuje wystąpienia programu sun.misc.Cleaner w specjalny sposób:

// Fast path for cleaners 
if (r instanceof Cleaner) { 
    ((Cleaner)r).clean(); 
    continue; 
} 

Oznacza to, że kod czyszczący jest wywoływany bezpośrednio z podajnika nici odniesienia, podczas gdy w standardowych zastosowań odniesienia musi być kolejkowane przez wątek obsługi odniesienia, a następnie z kolejki i przetwarzane przez inny wątek aplikacji.

+3

Nawiasem mówiąc, w Javie 9 znajduje się 'java.lang.ref.Cleaner', który jest standardowym zamiennikiem' sun.misc.Cleaner' – ZhekaKozlov

1

Jeśli polegasz na czymkolwiek w pakiecie sun.misc, ryzykujesz zniknięcie i złamanie kodu. Niektóre elementy są bardziej stabilne niż inne, ale często jest to zły pomysł (adwokat diabła: wiele metod w sun.misc.Unsafe jest faktycznie zaimplementowanych przez wewnętrzne elementy JVM, dzięki czemu są one szybsze niż napisany przez użytkownika kod JNI).

W tym przypadku myślę, że to zły pomysł: Cleaner to jedna z możliwych realizacji czyszczenia za pośrednictwem PhantomReference. Są inni; Google na przykład. Jeśli o to chodzi, możesz przyjrzeć się samemu sobie jako przykładowi użycia fantomowych odniesień.

Musisz będzie będzie potrzebował jakiegoś sprzątacza, jeśli masz zamiar mieć obiekty na stercie, które odnoszą się do obiektów pozapiecowych. W przeciwnym razie stworzysz prawdziwy wyciek pamięci po zebraniu tych obiektów na stosie.

Powiązane problemy