Praktycznie zastosowanie WeakRefów

2

Nawiązanie do https://4programmers.net/Mikroblogi/View/125655 .

O ile w przypadku zliczania referencji WeakRefy/Pointery wydają się być całkiem przydatne to za bardzo nie widzę zastosować dla języków z tracing gc. Jedyne co mi przychodzi do głowy to:

  • wewnętrzne, szyte na miarę niskopoziomowe pule obiektów do konkretnych zastosować
  • różnego rodzaje cache, ale w normalnych, biznesowych przypadkach lepiej chyba użyć gotowej biblioteki (np. Caffeine w Javie), który robi to pod spodem. W takim przypadku można powiedzieć, że Weak/Soft referencje są detalem implementacyjnym, bo nie używamy ich API
  • jak mamy burdel w kodzie i za bardzo nie ogarniamy czemu obiekty nam nie znikają albo chcemy dodać jakaś dodatkową informację do obiektu bez zmiany API i samego obiektu. Fajna opcja, ale chyba lepiej ogarnąć kod, żeby to nie było konieczne
  • ReferenceQueue i PhantomReference z Javy: fajnie brzmi, ale nie widzę praktycznych zastosować poza wspomnianymi cachami, które nie są oznaką, że coś poszło nie tak z designem

W jakich przypadkach użyliście tego ficzera?

2

różnego rodzaje cache, ale w normalnych, biznesowych przypadkach lepiej chyba użyć gotowej biblioteki (np. Caffeine w Javie), który robi to pod spodem. W takim przypadku można powiedzieć, że Weak/Soft referencje są detalem implementacyjnym, bo nie używamy ich API

No czyli oznacza to że WeakReference/SoftReference ma zastosowanie, przynajmniej w takiej Javie, ale Ty jak piszesz korpo biznesówke nie masz potrzeby tych mechanizmów bezpośrednio zastosować.
Dla mnie jest różnica między:

  • jako Java Developer nie używałem bezpośrednio nigdy SoftReference
  • SoftReference w Javie nie ma sensu

W końcu autor Caffeine tez korzysta z API Javy

2

@slsy:

Pewnie ficzery pojawiają się w języku (libce std), nie po to aby były masowo używane, ale aby były możliwe dośc wąskie/niszowe, ale ważne w realnej produkcji oprogramowania cele.
Weak ref dośc jasno dla wsyztskich jest przeznaczony w 95% do cache, a z tym się styka autor a nie klient kodu ... mnie to nie drażni.

Coś podobnego to zformalizowanie unsafe (vs kiedyś łażenie po pakietach sun.*) . Bezpieczne nigdy nie będzie, nigdy nie będzie używane przez więcej niż "paznokieć", ale ma swoje miejsce.

3

Piszesz aplikację desktopową, masz formatkę, jakiś kontroler i źródło zdarzeń. Stosujesz obserwatora z poziomu kontrolera, czyli kontroler ma uchwyt do formatki (musi mieć), sam siebie rejestruje jako listerera w źródle zdarzeń. Efekt jest taki, że aplikacja ma referencję na źródło zdarzeń, źródło zdarzeń ma referencję na kontroler, kontroler na formatkę. Ktoś zamyka formatkę, coś tam się dzieje i aplikacja zwalnia swój uchwyt na kontroler. Teoretycznie ktoś mógłby pomyśleć, że skoro kontroler robi eventSource.addListener(this), to kończąc się, powinien zrobić eventSource.removeListener(this), ale jakimś trafem, programiści o czymś takim zapominają (bo jest mit, że Java ma GC, a GC to taki magik, co sobie zawsze poradzi).
Prostym rozwiązaniem jest sprawienie, że w event source będziesz miał zamiast List<EventSourceListener> powiązanie przez WeakReference: List<WeakReference<EventSourceListener>>. Jeżeli tak zrobisz, to zniknięcie głównej referencji do formatki wystarczy, żeby została ona uprzątnięta, pomimo tego, że są do niej odwołania z innych miejsc.

Pisanie o tym, że WeakReference są nie potrzebne wynika chyba głównie z faktu, że w językach z GC rzadko (prawie nigdy) nie patrzy się na wycieki pamięci (formalnie nie są to wycieki). Ja zrozumiałem problem przez d... po 2 dniach zastanawiania się, czemu aplikacja sypie się z powodu OOM. Wystarczyło do utrwalenia wiedzy jak działa i jakie słabości ma GC :)

0

Pisanie o tym, że WeakReference są nie potrzebne wynika chyba głównie z faktu, że w językach z GC rzadko (prawie nigdy) nie patrzy się na wycieki pamięci (formalnie nie są to wycieki). Ja zrozumiałem problem przez d... po 2 dniach zastanawiania się, czemu aplikacja sypie się z powodu OOM. Wystarczyło do utrwalenia wiedzy jak działa i jakie słabości ma GC :)

Ja nie pamiętam specjalnie problemów z wyciekami pamięci w moich projektach, choć nigdy nie w Swingu nie pracowałem, a w kontenerach IoC javovych, takich jak Spring komponenty są zazwyczaj singletonami.

Stosujesz obserwatora z poziomu kontrolera, czyli kontroler ma uchwyt do formatki (musi mieć), sam siebie rejestruje jako listerera w źródle zdarzeń. Efekt jest taki, że aplikacja ma referencję na źródło zdarzeń, źródło zdarzeń ma referencję na kontroler, kontroler na formatkę. Ktoś zamyka formatkę, coś tam się dzieje i aplikacja zwalnia swój uchwyt na kontroler. Teoretycznie ktoś mógłby pomyśleć, że skoro kontroler robi eventSource.addListener(this), to kończąc się, powinien zrobić eventSource.removeListener(this), ale jakimś trafem, programiści o czymś takim zapominają (bo jest mit, że Java ma GC, a GC to taki magik, co sobie zawsze poradzi).

To jest rzeczywiście jeden z typowych przykładów, tylko zastanawiam sie na ile to realne/praktyczne - w tym sensie że jedyną aplikacją w Swingu która jest długo uruchomiona to Intellij ;]

1

@scibi_92: Nie przypominasz sobie kiedy sprawdziłeś i się okazało, że jest coś dużo pamięci zajętej, czy nie przypominasz sobie, że sprawdzałeś? Bo to spora różnica :) Gdybyś zrobił trochę aplikacji pod Androida, to prawdopodobnie nie byłbyś taki przekonany, jak to się wszystko samo robi. Różnica polega na tym, ze tam był limit pamięci, typu 20 MB na aplikację, jak został przekroczony, to łubudu i aplikacji nie ma. W Springu, konsylium senior devów zbierze się, pomyśli, spojrzy w kod i powie, no trudno, rozbudowaliśmy aplikację i tyle potrzebuje. Czesiek kliknie w konsolce, że teraz używamy instancji high memory i po bólu.
W Swingu, też problem nie zostanie zauważony, bo czy aplikacja zużywa 10 MB, czy 300MB - kogo to interesuje. Zużywa, to zużywa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1