2016-07-28 11 views
7

Przeczytałem wiele artykułów, jak działa finalizator. Oto moje zrozumienie: Jeśli klasa sfinalizuje zaimplementowaną metodę, Jvm stworzy instancję Finalizera jako psa obserwującego na tym obiekcie.Sfinalizowane zawiera dużo pamięci 2,5 gig na 4 g

Po uruchomieniu GC oznaczałoby to, że obiekt ma zostać usunięty i dodał je do kolejki referencyjnej, a następnie wątek finalizatora wybierałby te obiekty z kolejki i wykonywał ich metodę końcową.

Moje pytanie brzmi: Jak znaleźć obiekt ze zrzutu sterty, którego metoda finalizacji nie została zakończona z jakiegoś powodu i zaczęła układać kolejkę odniesienia?

Czy kolejka referencyjna jest w określonej kolejności?

+2

prostu zastanawiasz: jakie są Twoje sposoby finalizatora robi? Dlaczego masz tak wiele obiektów, które chcą użyć metody, na której, przynajmniej teoretycznie, nikt nie powinien polegać? – GhostCat

+0

Z kodu źródłowego wydaje się, że ReferenceQueue działa jak lista - zawiera obiekty referencyjne, każda referencja odnosi się do następnej referencji. Może pierwszy obiekt jest tym, czego potrzebujesz. Może powinieneś spróbować dodać aspekt przy sfinalizowaniu metody i dodać trochę rejestrowania (np. Wywołanie Finalizuj dla xxx; Finalizacja zakończona) - ostatni wpis w wierszu wskaże obiekt, który został rozpoczęty do sfinalizowania, ale finalizacja nie została zakończona . – ekaerovets

+0

Prawdopodobnie pójdę w drugą stronę i wykonam wyszukiwanie tekstowe dla klas, które mają nietrywialne implementacje 'finalize()' - czy w twojej bazie kodów jest zbyt wielu kandydatów? – Hulk

Odpowiedz

0

To może nie być odpowiedź, której szukasz, ale czy rozważałeś użycie PhantomReference zamiast przesłonić finalize()? Oto article, który mówi o tym.

Podstawowym założeniem jest to, że nie zaleca się polegać na finalyze() metody do oczyszczania pre-mortem ponieważ

  • Nie można przewidzieć, kiedy zostanie ona wywołana.
  • Zajmuje zasoby z JVM.
  • Może to zapobiec gromadzeniu śmieci w obiektach.

PhantomReference zapewnia bardziej przejrzysty sposób wywoływania akcji po usunięciu obiektu przez garbage collector.

Object objectToHandle = new Object(); 
ReferenceQueue queue = new ReferenceQueue(); 
PhantomReference reference = new PhantomReference(objectToHandle, queue); 

Gdy objectToHandle zostaną usunięte z pamięci przez śmieciarza jego reference zostaną dodane do queue. Możesz to wykryć dzwoniąc pod numer queue.remove() i wykonać wtedy akcję oczyszczania.

// will block until a reference becomes available 
Reference removedRef = queue.remove(); 
//.. you can now perform clean-up actions 

Uwaga: PhantomReference.get() zawsze zwraca null, więc niemożliwe jest, aby przywrócić obiekt po to został już usunięty z pamięci.

0

Tak, możesz pobrać obiekt ze zrzutu sterty.

pierwsze finalizator ref zostaną usunięte z kolejki w java.lang.ref.Finalizer.FinalizerThread#run, potem runFinalizer zostanie usunięty z podwójnie połączonego liście Niezakonczone odn w metodzie remove.

Ale można znaleźć ten ref, bo wiesz, że korzeń GC (istnieje na stosie FinalizerThread za)

Jak go znaleźć w Eclipse MAT:

  1. idź do histogramu i filtrem przez klasy Javy .lang.ref.Finalizer
  2. kliknij prawym przyciskiem myszy na wiersz z finalizatorami -> Połącz najkrótsze ścieżki z korzeniami gc z wszystkimi poprawkami.
  3. Rozwiń wiersz za pomocą FinalizerThread (zwykle powinien zawierać jeden obiekt java.lang.Finalizator)
  4. Kliknij na tym rozszerzonym rzędu, aw panelu inspektora można kliknąć na zakładce Atrybuty sfinalizowane obiekt będzie referent enter image description here
+0

Dzięki za odpowiedź. Nie widzę opcji dla panelu inspektorów. Jak otworzyć panel inspektorów. –

+0

Nieważne. Dziękuję bardzo za Twoją pomoc. Udało mi się znaleźć opcję. –

Powiązane problemy