Мы начинаем экспериментировать с реализацией наших внутренних сервисов с использованием 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? , на которую я посмотрю, но хотел получить резервную копию о том, выглядит ли область видимости действительной причиной.
Надеюсь, вы сможете помочь, спасибо.