Приложение CDI и зависимые области могут влиять на сборку мусора?

Мы начинаем экспериментировать с реализацией наших серверных служб с помощью CDI. Сценарий таков:

EJB с @Startup запускается при развертывании EAR. Bean-компонент ApplicationScoped внедряется в это:

@ApplicationScoped
public class JobPlatform {

    private PooledExecutor threadHolder;

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

Компонент также имеет метод Observer, который при наблюдении события получает рабочий компонент из экземпляра workerSource и помещает его в threadPool, где он в конечном итоге выполняется до завершения.

Все работает хорошо. Однако... мы начали замечать проблемы со сборкой мусора. Гистограмма кучи JMAP показывает, что многие из этих рабочих слоняются без сбора мусора.

Мы считаем, что это связано с комбинацией охвата CDI. Страница API для @Dependant (http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html) более четко подтверждает содержание документации:

  • Экземпляр компонента с областью видимости @Dependent, введенный в поле, конструктор компонента или метод инициализатора, является зависимым объектом экземпляра класса компонента или компонента Java EE, в который он был введен.
  • Экземпляр компонента с областью действия @Dependent, внедренный в метод производителя, является зависимым объектом создаваемого экземпляра компонента метода производителя.
  • Экземпляр компонента с областью действия @Dependent, полученный прямым вызовом экземпляра, является зависимым объектом экземпляра экземпляра.

Итак, после этого:

  • Bean-компонент workerSource привязан к JobPlatform и, следовательно, имеет время жизни ApplicationScoped.
  • Все рабочие компоненты, полученные с помощью этого экземпляра, привязываются к нему и, следовательно, имеют время жизни ApplicationScoped
  • Поскольку beanstore контекста ApplicationScoped (мое знание терминологии здесь становится немного туманным) по-прежнему имеет ссылку на рабочие bean-компоненты, они не уничтожаются/не собираются мусором

Кто-нибудь, использующий CDI, согласен с этим? Сталкивались ли вы с отсутствием сборки мусора, и если да, то можете ли вы предложить какие-либо обходные пути?

Рабочие не могут быть ApplicationScoped, но платформа должна быть. Если бы мы создали собственный WorkerScope (о-о-о...) и аннотировали им каждый рабочий класс, было бы этого достаточно, чтобы отделить зависимость между рабочим потоком и источником экземпляра?

Есть также несколько предложений по адресу Можно ли уничтожить область CDI?, на который я рассмотрю, но мне нужна дополнительная информация о том, выглядит ли область видимости уважительной причиной.

Надеюсь, вы можете помочь, спасибо.


person Ben Kirby    schedule 05.12.2011    source источник


Ответы (2)


Ваше понимание правильное. Это было упущением в спецификации, и это будет исправлено в CDI 1.1. Instance может иметь утечку памяти, как вы описали, при использовании в долговременной области, такой как SessionScoped или ApplicationScoped. Что вам нужно сделать, так это получить Contextual или Bean для экземпляра и уничтожить его таким образом.

Для того, что вы делаете, и чтобы избежать утечки памяти, вам лучше всего использовать методы BeanManager для создания экземпляров (таким образом вы также будете иметь дескриптор Bean и сможете его уничтожить) вместо Instance.

person LightGuard    schedule 06.12.2011
comment
Большое спасибо, что так быстро ответили - приятно знать, что это признанная проблема. Сейчас попробую обходной путь! Ваше здоровье! - person Ben Kirby; 06.12.2011
comment
Для всех, кто читает здесь, обратите внимание, что Weld 1.1 реализует CDI 1.0, а не CDI 1.1. - person Craig Ringer; 18.07.2012
comment
Правильный Крейг. Weld 2.0 реализует CDI 1.1 (да, я знаю, что нумерация странная). Если вы хотите увидеть, на что будет похож CDI 1.1, попробуйте Weld 2.0. Я считаю, что есть специальные сборки JBoss AS7, которые включают Weld 2.0. - person LightGuard; 19.07.2012
comment
Как это изменилось в CDI 1.1? - person Tom Anderson; 15.11.2012
comment
@TomAnderson В экземпляре будет метод удаления или уничтожения (не помню точное имя), который освободит созданный экземпляр, когда вы закончите его использовать. - person LightGuard; 15.11.2012

Изучая реализацию предложенного Джейсоном обходного пути, я нашел еще несколько ресурсов, касающихся этой проблемы:

Проблема: https://issues.jboss.org/browse/CDI-139 и https://issues.jboss.org/browse/WELD-920

Пример операций beanManager: https://issues.jboss.org/browse/CDI-14?focusedCommentId=12601344&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-12601344

or org.jboss.seam.faces.util.BeanManagerUtils

person Ben Kirby    schedule 06.12.2011