2010-08-11 12 views
6

Mam aplikację przeglądarki Swing z błędem, który po dodaniu/usunięciu do/z GUI pamięć nie jest zwolniona dla tych obiektów i próbuję wyśledzić, co się na nich trzyma. Problem polega na tym, że nie wiem, jak stwierdzić, kiedy coś zostało w pełni uwolnione z pamięci.Jak określić, kiedy pamięć obiektu Java zostanie zwolniona?

Czy można określić, czy obiekt został zwolniony z pamięci? Jestem przyzwyczajony do Celu-C, w którym istnieje kilka sposobów na powiedzenie.

Dzięki

+0

(FWIW, to zwykle jest słuchacz). –

+0

Myślałem, że to możliwe, ale starałem się usunąć wszystkie actionListeners i componentListeners – Shizam

Odpowiedz

6

Naprawdę nie można tego zrobić w Javie. Wszystkie odpowiedzi, które mówią o finalizatorach, naprawdę nie są tym, na co masz ochotę.

Najlepsze, co możesz zrobić, to zakodować PhantomReference w sondzie ReferenceQueue i poll, dopóki nie uzyskasz referencji.

final ReferenceQueue rq = new ReferenceQueue(); 
final PhantomReference phantom = new PhantomReference(referenceToObjectYouWantToTrack, rq); 

Chcesz przeczytać odpowiedź Petera Koflera tutaj (to wyjaśnia, co PhantomReference jest):

Have you ever used Phantom reference in any project?

Bardzo ciekawy przeczytać tutaj:

http://www.kdgregory.com/index.php?page=java.refobj

Zasadniczo "Używam PhantomReference w projekcie, w którym jeden specjalny rodzaj pamięci podręcznej musi zostać obliczony jeden raz, kiedy oprogramowanie zostało zainstalowane. Aby skutecznie obliczyć pamięć podręczną (dyskową), potrzebna jest gigantyczna ilość pamięci (im więcej, tym lepiej). Używam PhantomReference do śledzenia "prawie dokładnie" kiedy ta gigantyczna ilość pamięci zostanie zwolniona.

+0

Dobre informacje i linki, wygląda na to, że Peter sugeruje użycie profilera. – Shizam

+0

Ponieważ nie ma problemu, że finalizatorzy mogą rozwiązać problem braku PhantomReferences, zaktualizowałem swoją odpowiedź. Uważam, że finalizatorzy są "wystarczająco dobrzy" dla tego, co OP robi, ale zdaję sobie sprawę, że nie powinienem zachęcać do stosowania technik pół-deprecjonowania. –

+0

Do tej pory profilery, które próbowałem, nie mają rozdzielczości, aby pokazać, czy pojedynczy obiekt jest zwolniony. Wygląda na to, że ta odpowiedź (PhantomReferences) może być najlepszym narzędziem, ale mam problem ze znalezieniem przykładu użycia go do śledzenia tylko zwolnionych obiektów. Przykład w kdgregory służy do śledzenia połączeń SQL. Czym dokładnie odpytywam w poszukiwaniu wartości null, referenceQueue lub jakiejś innej listy śledzenia? – Shizam

3

Edit:

Jak NoozNooz42 wskazał, A PhantomReference może zrobić wszystko, co może, bez finalizator obecnych problemów finalizatory. Zachęcam więc do korzystania z PhantomReferences nad rozszerzeniem finalize(). Zachowuję swój pierwotny post w takcie, ponieważ myślę, że programiści Java powinni przynajmniej wiedzieć, że istnieje finalize().

Original post:

Każda klasa Java ma finalize() metodę, która pobiera uruchomić, gdy nie ma innych obiektów posiadają odniesienie do tej klasy. Możesz przedłużyć tę metodę w następujący sposób:

protected void finalize() throws Throwable { 
    try { 
     // Do whatever you want 
    } finally { 
     super.finalize(); 
    } 
} 

Dzięki temu możesz dowiedzieć się, czy coś zawiera odniesienie do przedmiotowych obiektów. Upewnij się, że zawsze dzwonisz pod numer super.finalize(), jeśli używasz tego podejścia.

referencyjny na zakończenia:

http://java.sun.com/developer/technicalArticles/javase/finalization/

+2

Należy unikać finalizatorów w Javie, ponieważ nie dają one gwarancji, gdy obiekty są rzeczywiście zbierane. Sfinalizowanie działa również wtedy, gdy instancja kwalifikuje się do gromadzenia. Zwykle problematyczne obiekty są przechowywane w pamięci przez inne instancje, więc finalizacja nie pomaga. Zobacz także tutaj: http://my.safaribooksonline.com/0201310058/ch02lev1sec6 (Efektywna Java Josh Blocha) –

+0

@jwachter: Dobrze, ale twój link wymaga zalogowania się, aby przeczytać. –

+0

@Justin Ardini: finalizacja się dzieje ** WAY BEFORE ** obiekt jest GC'ed. Zobacz moją odpowiedź: PO jest po PhantomReference, a nie finalizatorach. – NoozNooz42

1

Spróbuj YourKit. To profiler Java, który może pokazać ci użycie pamięci i co do cholery się dzieje. IIRC, darmowa wersja próbna może być zintegrowana z Eclipse i ma wszystkie funkcje płatnej wersji (ma tylko limit czasu).

3

Istnieje wiele sposobów wykrywania wycieków pamięci. Oto trzy obecnie jestem na myśli:

  1. Dołączanie Profiler aplikacji (Netbeans lub Eclipse TPTP powinny być użyteczne tutaj)
  2. Wykonywanie zrzutu sterty i analizować (z Eclipse Memory Analyzer) co instancje klasy są utrzymywane w pamięci za pomocą innych instancji.
  3. Dołączanie VisualVM do śledzenia stanu zbierania śmieci.
+0

, ale pytanie nie wspomniało o żadnym ** wycieku pamięci **. OP chce tylko śledzić, kiedy obiekt jest GC. – NoozNooz42

+0

Niestety # 1 nigdy nie działało dla mojego apletu, nigdy nie zrozumiałem dlaczego. Sprawdzę też VisualVM, obecnie próbuję YourKit. – Shizam

+0

@ NoozNooz42 masz rację. Ale myślę, że zwykle szukasz tylko wtedy, gdy coś jest zbierane, jeśli jest problem z pamięcią. –

Powiązane problemy