sobota, 15 sierpnia 2009

Słabe referencje... z czym to się je?

Dzisiaj święto Wojska Polskiego. Parady wojskowej nie będzie z powodu kryzysu, ale sklepy (z zupełnie zresztą innego powodu) pozamykane. A jeść trzeba...

Może skuszę się na słabą referencję... ale z czym to się je?

Referencja jak referencja, spotkał się z nią każdy:

String string = new String("123");

Słaba referencja wygląda trochę inaczej

Reference<String> refString = new WeakReference<String>(new String("123"));

a dostęp do obiektu, na który referencja wskazuje uzyskujemy za pomocą wywołania metody get()

refString,get();

Nie o wygląd jednak tutaj chodzi.

Dopóki obiekt w naszym programie wskazywany jest przez zwykłą referencję, nie zostanie on usunięty z pamięci przez jakże uwielbiany przez wszystkich Garbage Collector.

Natomiast obiekt wskazywany przez słabą referencję, może być usunięty przez GC jeżeli zacznie brakować pamięci, mimo, że referencja do niego cały czas jest obecna w programie. Metoda get() zwróci wtedy wartość null.

Nie wierzysz?

Oto krótki program obrazujący działanie słabych (i mocnych) referencji:

package pl.matt;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;


public class WeakReferenceTest {

int[] tab = new int[1024];

public static void main(String[] args) {
// zwykła referencja
String string = new String("123");

// słaba referencja
Reference<String> refString = new WeakReference<String>(new String("456"));

System.out.println(string);
System.out.println(refString.get());

java.util.List<WeakReferenceTest> list = new ArrayList<WeakReferenceTest>();

for (int i = 0; i < 1000000; i++) {
WeakReferenceTest test = new WeakReferenceTest();
list.add(test);
if (refString.get() == null) {
System.out.println(string);
System.out.println(i + " " + refString.get());
break;
}
}
}

}

Program w pętli przydziela pamięć tworząc nowe obiekty klasy WeakReferenceTest(). W pewnym momencie zaczyna się uruchamiać Garbage Collector i usuwa z pamięci obiekt który wskazywała słaba referencja.

Oprócz słabych referencji, w javie mamy jeszcze "średnio mocne" referencje SoftReference. Zasada ich działania jest podobna, z tym, że obiekty przez nie wskazywane żyją dłużej.

Obiekt wskazywany przez miękką referencję zostanie usunięty z pamięci tuż przed rzuceniem wyjątku java.lang.OutOfMemoryError.

Doskonałe narzędzia, to implementacji mechanizmów pamięci podręcznej.

Żeby dopełnić obrazu całości... są jeszcze referencje fantomowe PhantomReference. Obiekty wskazywane przez te referencje są usuwane przy każdym uruchomieniu GC, o ile nie wskazuje na nie żadna inna referencja. Można je stosować, aby mieć informację o tym, kiedy dany obiekt został usunięty z pamięci.

Aż się głodny zrobiłem, czas chyba zjeść coś bardziej konkretnego.

PS. Czego używacie do przeglądania RSSów? Ja jak dotąd Thunderbirda, ale ciągle szukam czegoś lepszego.

14 komentarzy:

KosciaK pisze...

Co do referencji - to ciężko coś dodać

A co do RSSów - jeśli używasz Firefoxa to polecam WizzRSS

Krzysiek pisze...

ad. "ps"
Osobiście używam Google Reader, zacząłem głównie z powodu historii i wyszukiwania w niej. Potem próbowałem czegoś desktopowego (ze trzy cosie) i nie przekonało mnie.

Pozdrawiam,
Krzysztof Kowalczyk

pedro pisze...

Ważne by pamiętać że taka referencja może stać się nullem w każdym momencie.
Więcej http://pietrowski.info/2009/04/weakreference-common-mistake/

WooKasZ pisze...

fajny art :)

a co do RSS do Google Reader.

Pozdrawiam !

Tomasz Chorwat pisze...

Muszę nie zgodzić się z zdaniem:
Dopóki obiekt w naszym programie wskazywany jest przez zwykłą referencję, nie zostanie on usunięty z pamięci przez jakże uwielbiany przez wszystkich Garbage Collector.
Jest ono nieprawdziwe i wprowadza w błąd.

Tomasz Chorwat pisze...

Opis PhantomReference. Obiekty wskazywane przez te referencje są usuwane przy każdym uruchomieniu GC, o ile nie wskazuje na nie żadna inna referencja jest również nieprawdziwy.

koziołek pisze...

Thnderbird, a ostatnio kombinuję z twoim pluginem do eclipse.

Tomasz Bartczak pisze...

@Tomasz Chorwat
No to skoryguj, będzie większa wartość dodana.

RSS:
Ja używam zwykłego firefoxa + plugin boox który zapamiętuje, które posty już czytałem.

Tomasz Chorwat pisze...

A co to wiki?
Jeśli już ktoś poświęca swój cenny czas na przekazanie innym swej wiedzy to mógłby się już postarać i nie wprowadzać innych w błąd.
Nie mówię o szczegółach ale o elementarnych błędach.

Michal Margiel pisze...

@Tomasz:
Ale to jaki sens ma Twoja wypowiedź? Jeśli uważasz, że został popełniony błąd, to zaraz po kropce powinieneś wskazać poprawną wersję.

Ludzie poświęcają swój cenny czas na pisania blogów aby przepływ wiedzy był obustronny a nie jedno. Inaczej niewielu ludzi było by tym zainteresowanych.

Życzę na przyszłośc trochę mniej zaciętości a więcej pozytywnego nastawienia do świata i ludzi.

@Mateusz

W jaki sposób kolorujesz składnie i formatujesz kod?

Tomasz Chorwat pisze...

Przecież napisałem:
zdanie: Dopóki obiekt w naszym programie wskazywany jest przez zwykłą referencję, nie zostanie on usunięty z pamięci przez jakże uwielbiany przez wszystkich Garbage Collector. jest nieprawdziwe.

Czy gdybym napisał:
Jeśli na obiekt wskazuje zwykła referencja nie oznacza to, że GC nie zwolni takiego obiektu to czy merytorycznie moja wypowiedź coś by zmieniła?

No dobrze, może rzeczywiście mógłbym uzasadnić swoje stwierdzenie. Otóż to, że istnieje referencja do obiektu (zwykła) nie oznacza, że taki obiekt jest "nietykalny" dla GC. Dla GC nietykalne są obiekty, do których istnieje ścieżka referencji ze stosu aktywnego wątku w programie. Można sobie wyobrazić, że gdzieś na stercie pozostały dwie instancje klas (po jednej z A i B), które to instancje posiadają referencje do siebie nawzajem. Na stercie nie ma, żadnych innych referencji do tych obiektów? Czy GC może, czy nie może zwolnić takie obiekty? Otóż może i zrobi to, gdy tylko będzie miał na to ochotę.

Na koniec wyjaśnienie mojej zaciętości. Ktoś popełnił artykuł na własnym blogu. Każdy może się mylić - również ja, Ty. Ale gdy ktoś wskazałby mi, że opowiadam bzdury na forum publicznym i wprowadzam w błąd mniej doświadczonych kolegów, to jednak starałbym się zweryfikować informacje, które zawarłem w poście. Tu nic takiego niestety nie miało miejsca. Trafiłem tu przez przypadek, czegoś szukając. Wybaczcie, że nie popełniłem od razu tego wywodu ale przecież jest to wiedza elementarna z zakresu referencji i działania gc. Zostawiłem swój post negujący dwa zdania, by post ten nie siał w umysłach innych dezinformacji i może zmusił autora do refleksji.
Pozdrawiam wszystkich.
Może sam coś wysmaruje na ten temat na moim blogu? Hmm może warto. Jak coś urodzę przez najbliższe dwa tygodnie dam znać.

Michal Margiel pisze...

@Tomasz:
"Można sobie wyobrazić, że gdzieś na stercie pozostały dwie instancje klas (po jednej z A i B), które to instancje posiadają referencje do siebie nawzajem. Na stercie nie ma, żadnych innych referencji do tych obiektów? Czy GC może, czy nie może zwolnić takie obiekty? Otóż może i zrobi to, gdy tylko będzie miał na to ochotę."

I to jest naprawdę ten elementarny błąd? No ja bym tak tego nie nazwał. Jak dla mnie to jest to dość specyficzny przypadek - który faktycznie Mateusz nie opisał. Ale słowa typu "elementarny błąd" czy wręcz "opowiadanie bzdur" i "wprowadzanie w błąd" są tu naprawdę nie na miejscu.

Oczywiście Mateusz mógłby swoją wypowiedź uściślić i w ogóle cały esej o tym napisać - to nie ma wątpliwości.

Faktem jest, że do odpowiednich sytuacji trzeba dobierać odpowiednie słowa. I tyle.

Pozdrawiam Cię serdecznie i z niecierpliwością czekam na Twój wpis, który, jak mniemam, będzie idealny pod każdym względem ;) Wszak nie dasz nam chyba pomyśleć ani przez chwilę, że "nie myli się tylko ten co nic nie robi".

Tomasz Chorwat pisze...

http://blog.tomasz.chorwat.pl/2009/09/odpoczywaj-w-pokoju-wiecznym.html

zapraszam do zapoznania się i zapewne pożytecznych uwag.

MZ pisze...

@MM do kolorowania i formatowania składni używam http://code.google.com/p/syntaxhighlighter/

@TC moje "obiekt w naszym programie" miało oznaczać właśnie "obiekt do którego istnieje ścieżka referencji ze stosu aktywnego wątku w programie". Widać nie każde uproszczenie jest zrozumiałe. Gratuluje postu i chęci podzielenia się wiedzą ze światem. W wolnej chwili na pewno go przeczytam.