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