2011-12-05 11 views
15

Zaczynamy eksperymentować z wdrażaniem naszych usług backendowych za pomocą CDI. Scenariusz jest następujący:Aplikacje i zakresy zależne CDI mogą konspirować, aby wpływać na wywóz śmieci?

EJB z @Startup jest uruchamiany po wdrożeniu EAR. ApplicationScoped fasola jest wstrzykiwany na to:

@ApplicationScoped 
public class JobPlatform { 

    private PooledExecutor threadHolder; 

    @Inject @Any 
    private Instance<Worker> workerSource; 
... 

Fasola ma również metodę obserwatorem, który, gdy obserwuje zdarzenie, dostaje fasoli robotnik z instancji workerSource i kładzie go na puli wątków, gdzie ostatecznie prowadzi Do ukończenia.

Wszystko działa dobrze. Jednak ... zaczęliśmy widzieć problemy ze zbieraniem śmieci. Histogram sterty JMAP pokazuje, że wielu z tych pracowników kręci się wokół, a nie-śmieci gromadzone.

Uważamy, że jest to spowodowane połączeniem scoringu CDI. Strona API dla @Dependant (http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html) wzmacnia jaśniej co w docs:

  • Instancja fasoli z zakresu @Dependent wtryskiwanego do pola, konstruktor fasoli lub metoda inicjująca jest zależny przedmiot komponent bean komponentu bean lub Java EE, do którego został on wstrzyknięty.
  • Instancja komponentu bean o zasięgu @Dependent wprowadzona do metody producenta jest zależnym obiektem produkowanej instancji komponentu bean metody producenta.
  • Instancja komponentu bean o zasięgu @Dependent uzyskana przez bezpośrednie wywołanie instancji jest zależnym obiektem wystąpienia instancji.

Więc po to:

  • workerSource fasola jest zobowiązany do JobPlatform, a zatem ma żywotność ApplicationScoped
  • Wszelkie fasola pracownik pobierane za pomocą tej instancji są zobowiązane do niego i dlatego istnieje okres trwałości ApplicationScoped:
  • Ponieważ magazyn bean kontekstu ApplicationScoped (moja znajomość terminologii jest tu nieco mglisty) nadal ma wartość do fasoli pracownika, nie są niszczone/zebrane śmieci

Czy ktoś używający CDI zgadza się z tym? Czy doświadczyłeś tego braku zbierania śmieci, a jeśli tak, czy możesz zaproponować jakieś obejścia?

Pracownicy nie mogą być ApplicationScoped, ale platforma musi być. Gdybyśmy stworzyli niestandardowy WorkerScope (uh ohhh ...) i dodali adnotację do każdej klasy klasy robotniczej, czy to wystarczy, aby oddzielić zależność między źródłem roboczym a źródłem?

Są też pewne sugestie na temat Is it possible to destroy a CDI scope?, na które przyjrzę się, ale chciałem zrobić kopię zapasową, czy określenie zakresu wygląda jak uzasadniony powód.

Mam nadzieję, że możesz pomóc, dzięki.

Odpowiedz

9

Twoje zrozumienie jest prawidłowe. Było to niedopatrzenie w specyfikacji i coś, co zostanie naprawione w CDI 1.1. Instance może mieć wyciek pamięci, tak jak opisałeś, gdy jest używany w długim zakresie, takim jak SessionScoped lub ApplicationScoped.To, co musisz zrobić, to uzyskać instancję Contextual lub Bean dla instancji i zniszczyć ją w ten sposób.

Za to, co robisz, i aby uniknąć wycieku pamięci, najlepiej jest użyć metod BeanManager do utworzenia instancji (w ten sposób będziesz mieć również uchwyt na Bean i możesz go zniszczyć) zamiast Instance.

+0

Wielkie dzięki za tak szybkie odzyskanie - dobrze wiedzieć, że jest rozpoznawalny kwestia. Sprawi, że obejście problemu będzie już możliwe! Twoje zdrowie! –

+0

Dla każdego, kto tu czyta, zauważ, że Weld 1.1 implementuje CDI 1.0, a nie CDI 1.1. –

+0

Popraw Craig. Weld 2.0 implementuje CDI 1.1 (tak, wiem, że numeracja jest dziwna). Jeśli chcesz zobaczyć, jaki będzie CDI 1.1, wypróbuj Weld 2.0. Wierzę, że istnieją specjalne kompilacje JBoss AS7, które obejmują Weld 2.0. – LightGuard