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)

Reply via email to