Georg Tsakumagos created TOMEE-4192:
---------------------------------------
Summary: ApplicationComposers do not clear GC references on release
Key: TOMEE-4192
URL: https://issues.apache.org/jira/browse/TOMEE-4192
Project: TomEE
Issue Type: Wish
Reporter: Georg Tsakumagos
The ApplicationComposers do not clear all references on release which could
result in very high memory consumption for tests if injected classes a heavy
weight. An analysis of heap dumps shows different implementations holding
references.
{code:java|title=Example fat bean}
@ApplicationScoped
public class FatBean {
private static final long serialVersionUID = -5814319377355637770L;
private String payload;
public FatBean() {
super();
/*
* Big Memory Payload
*/
char[] array = new char[1024 * 1024 * 128];
Arrays.fill(array, '@');
this.payload = new String(array);
this.logger.info("Init FatProject Bean.");
}
}
{code}
Top overcome this bad behaviuour i've written an junit-extension to tear down
all references by reflection. I like to get rid of this hack.
{code:java|title=Teardown code}
/**
* Workaround for memory hogs in <em>OpenEJB</em>. Several components hold
* references via {@link ThreadLocal} {@link List} and other instances. They
are
* not cleared on shutdown and prevent the <em>GC</em> from cleanup.
*
* @param composer The Composer to dispose.
* @param testContext The TestContext.
*/
private void tearDown(ApplicationComposers composer, ExtensionContext
testContext) {
this.logger.info(LOG_INFO_DESTROY,
testContext.getTestInstanceLifecycle().orElse(null), composer);
try {
/*
* Reflection magic
*/
Field field =
composer.getClass().getDeclaredField(REFLECTION_FIELD_APPCONTEXT);
field.setAccessible(true);
AppContext context = (AppContext) field.get(composer);
/*
* Clear Lists.
*/
context.getWebContexts().clear();
context.getInjections().clear();
/*
* Another greedy hog
*/
try {
SystemInstance systemInstance = context.getSystemInstance();
if (null != systemInstance) {
field =
systemInstance.getClass().getDeclaredField(REFLECTION_FIELD_COMPONENTS);
field.setAccessible(true);
field.set(systemInstance, null);
}
} catch (final Throwable exception) {
this.logger.error(LOG_ERROR_TEAR_DOWN, exception);
}
/*
* Another greedy hog
*/
WebBeansContext webBeansContext = context.getWebBeansContext();
if (null != webBeansContext) {
try {
field =
webBeansContext.getClass().getDeclaredField(REFLECTION_FIELD_NOTIFICATIONMANAGER);
field.setAccessible(true);
field.set(webBeansContext, null);
} catch (final Throwable exception) {
this.logger.error(LOG_ERROR_TEAR_DOWN, exception);
}
try {
field =
webBeansContext.getClass().getDeclaredField(REFLECTION_FIELD_INTERCEPTORDECORATORPROXYFACTORY);
field.setAccessible(true);
field.set(webBeansContext, null);
} catch (final Throwable exception) {
this.logger.error(LOG_ERROR_TEAR_DOWN, exception);
}
}
} catch (final Throwable exception) {
this.logger.error(LOG_ERROR_TEAR_DOWN, exception);
}
}
{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)