#java #dependency-injection #rcp #e4
#java #внедрение зависимостей #rcp #e4
Вопрос:
Я использую внедрение зависимостей (DI) внутри приложения Eclipse RCP. У меня есть много классов, которые выполняют код, аналогичный приведенному ниже:
public class SomeClass {
@Inject
private IEclipseContext context;
private SomeObject void someMethod(){
SomeObject someObject =
ContextInjectionFactory.make(SomeObject.class, context);
// Do stuff with someObject
}
}
Когда я отслеживаю приложение с помощью jvisualvm, я замечаю, что из-за этого происходит утечка памяти. Объект EclipseContext продолжает расти, пока в конечном итоге не закончится память.
Если я сделаю следующее, утечка памяти исчезнет:
public class SomeClass {
@Inject
private IEclipseContext context;
private SomeObject void someMethod(){
IEclipseContext childContext = context.createChild();
SomeObject someObject =
ContextInjectionFactory.make(SomeObject.class, childContext);
childContext.dispose();
// Do stuff with someObject
}
}
Я не видел никакой документации, которая поддерживала бы мой обходной путь. Есть ли какие-либо негативные побочные эффекты при удалении дочернего CONTEXT после создания класса? Есть ли в целом лучший подход при использовании CIF, с которым я не сталкивался?
Как бы то ни было, в моем коде много классов, некоторые из которых помечены @Singleton / @Creatable . Я не уверен, что это будет вызвано удаленным родительским контекстом.
Спасибо!
Комментарии:
1. Я не видел никаких сообщений о наличии утечки, и я не видел этого в своем коде.
2. Да, это определенно странно. Единственное отличие в моем коде — это то, что показано выше. Я создаю много объектов, большинство из которых уничтожаются, когда они больше не нужны. В течение нескольких дней я замечаю, что в основном контексте есть миллионы ссылок на объекты, и он растет, пока я не получу ошибку памяти. Если я сделаю обходной путь, все будет хорошо. Знаете ли вы о каких-либо негативных последствиях использования обходного пути?
3. Если что-либо, что вы делаете с дочерним контекстом, вводит IEclipeContext, это приведет к доступу к удаленному контексту, если он попытается получить к нему доступ позже. Это затрудняет отладку ошибок. Знаете ли вы, в каком поле в классе EclipseContext хранятся все эти ссылки?
4. Похоже (с помощью инструмента Eclipse Memory Analyzer), что под основным EclipseContext находятся миллионы отслеживаемых элементов computationext и ContextInjectionListener.
5. «Исходный текст org.eclipse.e4.core.internal.contexts. Отслеживаемый вычислительный текст» и «контекст org.eclipse.e4.core.internal.контексты. ContextObjectSupplier$ContextInjectionListener»
Ответ №1:
Когда вы используете инъекцию для установки полей в вашем классе следующим образом:
public class Test
{
@Inject
private StatusReporter rep;
@Inject
private IEventBroker broker;
public Test()
{
}
}
Eclipse должен отслеживать каждое введенное поле, чтобы оно могло повторно ввести поле, если значение в контексте Eclipse изменится. Это включает в себя создание TrackableComputationExt
ContextInjectionListener
объектов и для каждого введенного поля.
Если вместо этого вы вводите значения в конструктор следующим образом:
public class Test
{
private StatusReporter rep;
private IEventBroker broker;
@Inject
public Test(StatusReporter rep, IEventBroker broker)
{
this.rep = rep;
this.broker = broker;
}
}
Eclipse не нужно отслеживать внедрение конструктора, поэтому эти объекты не создаются (но вы также не получите никаких обновлений, если будут изменены значения контекста).
При тестировании этого все еще создается один объект отслеживания внутреннего использования.
Комментарии:
1. Странно, что никто больше не упоминал то же самое, что и я, поскольку я вижу много кода, использующего инъекции полей против инъекций конструктора. Исчезают ли объекты отслеживания после того, как класс больше не используется? Если у меня есть коллекция объектов <Test> и я очищаю коллекцию, исчезают ли ссылки для отслеживания? Я предполагаю (по количеству экземпляров, которые я видел), что с помощью полевых инъекций они этого не делают (хотя я бы ожидал от них)
2. Ну, в Java нет способа отслеживать, когда что-то «уходит» (если где-то я не пропустил какие-то слабые ссылки), так что, вероятно, нет. Вероятно, они зависают, пока контекст не будет удален. Но этот код очень сложный и трудный для чтения (как обычно). Я думаю, что большинство людей используют инъекцию только для ограниченного числа объектов пользовательского интерфейса, поэтому не сталкивались с этим.