[ 
https://issues.apache.org/jira/browse/TOMEE-4192?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Georg Tsakumagos updated TOMEE-4192:
------------------------------------
    Attachment: GC-Root-For-Payload-before.png

> 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
>    Affects Versions: 9.0.0, 8.0.14
>            Reporter: Georg Tsakumagos
>            Priority: Major
>         Attachments: GC-Root-For-Payload-before.png
>
>
> 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. Having an project with many tests amplifies this problem enormous. 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