Мы начинаем экспериментировать с внедрением наших бэкэнд-сервисов с использованием CDI. Сценарий таков:
EJB с @Startup запускается при развертывании EAR. На него вводится ApplicationScoped bean:
@ApplicationScoped
public class JobPlatform {
private PooledExecutor threadHolder;
@Inject @Any
private Instance<Worker> workerSource;
...
bean также имеет метод Observer, который, когда наблюдается событие, получает рабочий bean из экземпляра employeeSource и помещает его в threadPool, где он в конечном итоге заканчивается.
Все работает красиво. Однако... мы начали видеть проблемы с сборкой мусора. Гистограмма кучи JMAP показывает, что многие из этих рабочих висят вокруг, не мусор собрал.
Мы полагаем, что это связано с комбинацией охвата CDI. Страница API для @Dependant (http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html) более четко подчеркивает, что в документах:
- Экземпляр bean с областью применения @Dependent, введенный в поле, конструктор bean или метод инициализации является зависимым объектом экземпляра класса компонента bean или Java EE, в который он был введен.
- Экземпляр bean с областью действия @Dependent, введенный в метод-производитель, является зависимым объектом создаваемого экземпляра метода bean.
- Экземпляр bean с областью видимости @Dependent, полученный прямым вызовом экземпляра, является зависимым объектом экземпляра экземпляра.
Итак, следуя этому:
- Рабочий файл bean привязан к JobPlatform и, следовательно, имеет срок службы ApplicationScoped
- Любой рабочий beans, полученный с помощью этого экземпляра, привязан к нему и, следовательно, имеет срок службы ApplicationScoped
- Поскольку beanstore контекста ApplicationScoped (мои знания терминологии здесь немного туманны) по-прежнему имеет ссылку на рабочего beans, они не уничтожаются/собираются мусора
Кто-нибудь, кто использует CDI, согласен с этим? Испытывали ли вы это отсутствие сбора мусора, и если да, можете ли вы предложить какие-либо обходные пути?
Рабочие не могут быть ApplicationScoped, но платформа должна быть. Если бы мы создали пользовательский WorkerScope (uh ohhh...) и аннотировали каждый рабочий класс с ним, было бы достаточно, чтобы отделить зависимость между рабочим и экземпляром?
Есть также некоторые предложения в Можно ли уничтожить область CDI?, на которую я буду смотреть, но хотел, чтобы какая-то резервная копия выглядела как действительная причина.
Надеюсь, вы сможете помочь, спасибо.