TranslationObjectSupplier seems to leak FieldRequestor? [message #1755932] |
Thu, 09 March 2017 11:29 |
Christian Mohr Messages: 34 Registered: June 2012 |
Member |
|
|
Hi,
while investigating some internal memory leaks we stumpled upon the TranslationObjetSupplier. It looks like it never actually removes FieldRequestor from its internal ListenerMap, even when the Class-Instances containing the @Translation annotation where already removed.
I tried to reproduce it in a simple application. I used the Eclipse E4-Template with Sample Classes and replaced the generated classes with the following ones:
The CustomComposites Class using the @Translation Annotation
public class CustomComposite extends Composite {
@Inject
@Translation
public Messages messages;
/**
* not used here for testshowcase, but needed in actual implementation
*/
@Inject
public IEclipseContext context;
@Inject
public CustomComposite(final Composite parent) {
super(parent, SWT.NONE);
setLayout(new GridLayout(2, false));
addDisposeListener(e -> destroy());
}
@PostConstruct
public void postConstruct() {
Label label = new Label(this, SWT.NONE);
label.setText(messages.myFirstLabel);
label = new Label(this, SWT.NONE);
label.setText(messages.mySecondLabel);
}
public void destroy() {
context.dispose();
}
}
The SamplePart for adding and removing "CustomComposites"
public class SamplePart {
List<CustomComposite> customComposites = new ArrayList<>();
@Inject
private IEclipseContext context;
@PostConstruct
public void createComposite(final Composite parent) {
parent.setLayout(new GridLayout(2, false));
Button buttonAdd = new Button(parent, SWT.PUSH);
buttonAdd.setText("ADD");
buttonAdd.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
IEclipseContext childContext = context.createChild("myChildContexts");
childContext.set(Composite.class, parent);
CustomComposite make = ContextInjectionFactory.make(CustomComposite.class, childContext);
customComposites.add(make);
make.requestLayout();
}
});
Button buttonRemove = new Button(parent, SWT.PUSH);
buttonRemove.setText("REMOVE");
buttonRemove.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
if (!customComposites.isEmpty()) {
CustomComposite composite = customComposites.get(customComposites.size() - 1);
customComposites.remove(composite);
composite.dispose();
parent.requestLayout();
}
}
});
}
}
And the Messages class (+ the translation file):
public class Messages {
public String myFirstLabel;
public String mySecondLabel;
}
While debugging you can see, that in the TranslationObjectSupplier, for each added CustomComposite, there is an additional FieldRequestor added to the internal list (addListener method). After disposing the CustomComposites, they won't get removed. With any Memory-Analyzer you can see that the amount of FieldRequestor- and IEclipseContext-Instances is growing.
Finally my question is whether this is a real bug, and i should open a bug report for it, or am i doing something completly wrong with the Annotation or EclipseContext-Handling.
Thanks for any help.
Regards,
Christian
[Updated on: Thu, 09 March 2017 11:38] Report message to a moderator
|
|
|
|
|
Re: TranslationObjectSupplier seems to leak FieldRequestor? [message #1755958 is a reply to message #1755949] |
Thu, 09 March 2017 15:07 |
Dirk Fauth Messages: 2902 Registered: July 2012 |
Senior Member |
|
|
Thanks.
Could you try to make use of the BaseMessageRegistry to see if that would solve the leakage?
For this you create a new message registry class like this:
@Creatable
public class MessageRegistry extends BaseMessageRegistry<Messages> {
@Override
@Inject
public void updateMessages(@Translation Messages messages) {
super.updateMessages(messages);
}
}
and use it in your composite like this:
public class CustomComposite extends Composite {
/**
* not used here for testshowcase, but needed in actual implementation
*/
@Inject
public IEclipseContext context;
@Inject
public CustomComposite(final Composite parent) {
super(parent, SWT.NONE);
setLayout(new GridLayout(2, false));
addDisposeListener(e -> destroy());
}
@PostConstruct
public void postConstruct(MessageRegistry registry) {
Label label = new Label(this, SWT.NONE);
registry.register(label::setText, m -> m.myFirstLabel);
label = new Label(this, SWT.NONE);
registry.register(label::setText, m -> m.mySecondLabel);
}
public void destroy() {
context.dispose();
}
}
As the references in the TranslationObjectSupplier are never cleaned up, I suspect the same behavior, I just want to be sure.
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03286 seconds