Application Server 7
  1. Application Server 7
  2. AS7-3733

AWT AppContext / EventQueue ClassLoader Memory Leaks

    Details

    • Similar Issues:
      Show 10 results 

      Description

      The use of libraries using awt components creates ClassLoader Memory Leaks. This is because the first call to the sun AppContext class makes a static reference to the current class loader.
      Same thing goes with the creation of the AWT Event Queue, as an example the use of the class java.awt.Color makes a static init call to java.awt.Toolkit which creates an AWT EventQueue despite the headless mode. The EventQueue also keep a reference to the current context with the class loader.

      The current work around I've found is to add a call to:

      java.awt.Toolkit.getDefaultToolkit();

      before the application gets loaded.
      This causes the EventQueue to be created and the AppContext to be initialized.
      Then, as the AWT static references are final, I get rid of this issue for the rest of the server lifecycle.
      I put this code in org.jboss.as.server.Main, just after line 91. However a proper solution would be to use org.apache.catalina.core.JreMemoryLeakPreventionListener which is present in the JBoss Web jar but not used... (cf. https://community.jboss.org/thread/164760 ) However the Tomcat code deals only with the AppContext, not the EventQueue!

        Activity

        Hide
        Remy Maucherat
        added a comment -

        AS7-3732: Although the issue causing the leak is different, the method to work around it should be the same, webapps in JBoss AS can use a listener like Tomcat does.

        Show
        Remy Maucherat
        added a comment - AS7-3732 : Although the issue causing the leak is different, the method to work around it should be the same, webapps in JBoss AS can use a listener like Tomcat does.
        Hide
        Philippe Guinot
        added a comment - - edited

        No it isn't.
        If I define a webapp listener, the current context will refer to the application's class loader and so the fix won't work.
        This patch need to be run outside the webapp...

        Show
        Philippe Guinot
        added a comment - - edited No it isn't. If I define a webapp listener, the current context will refer to the application's class loader and so the fix won't work. This patch need to be run outside the webapp...
        Hide
        Remy Maucherat
        added a comment -

        jboss-web.xml has container listener configuration, using the listener element and listener-type sub element with value "LIFECYCLE". This jira is not about web at all, anyway.

        Show
        Remy Maucherat
        added a comment - jboss-web.xml has container listener configuration, using the listener element and listener-type sub element with value "LIFECYCLE". This jira is not about web at all, anyway.
        Hide
        Philippe Guinot
        added a comment -

        Remy,

        Using a listener is not a good solution, I'm afraid. Because at that point the current context class loader is the application class loader.

        When the AWT Thread is created it refers so to the application's CL, hence the leak.

        So this is a code that must be called outside any application specific code. Maybe not the Web component if you want.. Feel free to re-affect this JIRA to anyone, but it should be reopened as long as the given workaround you suggested does not work.

        PS: using Thread.currentThread().setContextClassLoader(...) before creating a thread, does not prevent the child thread keeping a reference to the parent thread's CL. I wish it could, but it would be to easy.. A reference to the class loader is also kept in the inheritedAccessControlerContext.

        Show
        Philippe Guinot
        added a comment - Remy, Using a listener is not a good solution, I'm afraid. Because at that point the current context class loader is the application class loader. When the AWT Thread is created it refers so to the application's CL, hence the leak. So this is a code that must be called outside any application specific code. Maybe not the Web component if you want.. Feel free to re-affect this JIRA to anyone, but it should be reopened as long as the given workaround you suggested does not work. PS: using Thread.currentThread().setContextClassLoader(...) before creating a thread, does not prevent the child thread keeping a reference to the parent thread's CL. I wish it could, but it would be to easy.. A reference to the class loader is also kept in the inheritedAccessControlerContext.
        Hide
        Remy Maucherat
        added a comment -

        The context classloader is not yet bound during the init event, which is the one used by the Tomcat listener. I did sync with the Tomcat listener to have it at hand for people willing to hack, but it won't do the exact same thing since deployment is not the same [you can add your own "memoryleak" subsystem to cleanly replicate what Tomcat is doing if you really need it].

        It is up to the application server to add these leaks hacking though, and it doesn't seem to be something that will happen.

        Show
        Remy Maucherat
        added a comment - The context classloader is not yet bound during the init event, which is the one used by the Tomcat listener. I did sync with the Tomcat listener to have it at hand for people willing to hack, but it won't do the exact same thing since deployment is not the same [you can add your own "memoryleak" subsystem to cleanly replicate what Tomcat is doing if you really need it] . It is up to the application server to add these leaks hacking though, and it doesn't seem to be something that will happen.
        Hide
        Philippe Guinot
        added a comment -

        Thank you.

        I don't mind creating my own listener after all, because I may need to init other things at startup.

        However, with this listener added in jboss-web.xml
        <listener>
        <class-name>mypackage.MemoryLeakPreventionListener</class-name>
        <listener-type>LIFECYCLE</listener-type>
        </listener>
        It is actually called only since the 'after-deploy' event. Maybe I haven't declared it in the right place... Where is that jboss-web.xml supposed to be ?

        Show
        Philippe Guinot
        added a comment - Thank you. I don't mind creating my own listener after all, because I may need to init other things at startup. However, with this listener added in jboss-web.xml <listener> <class-name>mypackage.MemoryLeakPreventionListener</class-name> <listener-type>LIFECYCLE</listener-type> </listener> It is actually called only since the 'after-deploy' event. Maybe I haven't declared it in the right place... Where is that jboss-web.xml supposed to be ?
        Hide
        Remy Maucherat
        added a comment -

        Ok, they get added, but too late. It won't work unless I add the configured listeners a little bit earlier, which is possible.

        Show
        Remy Maucherat
        added a comment - Ok, they get added, but too late. It won't work unless I add the configured listeners a little bit earlier, which is possible.
        Hide
        Remy Maucherat
        added a comment -

        The lifecycle listeners should now get all the events, including init and before_start.

        Show
        Remy Maucherat
        added a comment - The lifecycle listeners should now get all the events, including init and before_start.

          People

          • Assignee:
            Remy Maucherat
            Reporter:
            Philippe Guinot
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: