CDI Application и зависимые области видимости могут влиять на сбор мусора? - PullRequest
16 голосов
/ 05 декабря 2011

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

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

@ApplicationScoped
public class JobPlatform {

    private PooledExecutor threadHolder;

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

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

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

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

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

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

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

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

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

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

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

Ответы [ 2 ]

9 голосов
/ 06 декабря 2011

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

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

2 голосов
/ 06 декабря 2011

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

Проблема: 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

или org.jboss.seam.faces.util.BeanManagerUtils

...