javaserverfaces
  1. javaserverfaces
  2. JAVASERVERFACES-2746

UIComponentBase may leak classoaders / PermGen memory

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.1.8, 2.1.19
    • Fix Version/s: 2.2.5
    • Component/s: None
    • Labels:
      None
    • Environment:

      Tested with 2.1.8 but AFAI can tell no changes have been made in this regard in 2.1.19

      Description

      The static descriptors cache in javax.faces.component.UIComponentBase can cause classloader / PermGen memory leaks if embedded in container.
      Somebody tried to consider that:

      • <p><strong>IMPLEMENTATION NOTE</strong> - This is implemented as a
      • <code>WeakHashMap</code> so that, even if this class is embedded in a
      • container's class loader that is a parent to webapp class loaders,
      • references to the classes will eventually expire.</p>

      However, with a WeakHashMap only the key is weak referenced, the value still has a strong reference. In this case the value is a Map<String, PropertyDescriptor> and in that PropertyDescriptor there is a java.util.Hashtable table with a key "type" whose value may be a Class loaded within the web applications classloader, and the strong reference chain to that class will prevent the classloader from being garbage collected upon redeploy.

      1. changebundle.txt
        247 kB
        Manfred Riem
      2. changebundle.txt
        7 kB
        Manfred Riem

        Activity

        Hide
        Mattias Jiderhamn added a comment - - edited

        As is described briefly on https://github.com/mjiderhamn/classloader-leak-prevention :

        By annotating the test class with @RunWith(JUnitClassloaderRunner.class) my test framework asserts that the classloader cannot be properly garbage collected after the tests have run. That is, you only need to add to the test case the code that triggers the leak and the framework will do the assertions for you.

        If you want the framework to assert that there is no leak, annotate the test method with @Leaks(false).
        In this case, adding @Leaks(false) makes the test fail, and what you probably want to do is change the implementation until the test passes with @Leaks(false).

        It is also possible to test that a leak prevention workaround will allow the classloader to be garbage collected by using the @LeakPreventor annotation. So in case you intend to add some cleanup method that needs to be explicitly called, you should create a Runnable that calls the cleanup method, and annotate the test class with @LeakPreventor(MyCleanupRunnable.class)

        Just get back to me if you need further instructions!

        Show
        Mattias Jiderhamn added a comment - - edited As is described briefly on https://github.com/mjiderhamn/classloader-leak-prevention : By annotating the test class with @RunWith(JUnitClassloaderRunner.class) my test framework asserts that the classloader cannot be properly garbage collected after the tests have run. That is, you only need to add to the test case the code that triggers the leak and the framework will do the assertions for you. If you want the framework to assert that there is no leak , annotate the test method with @Leaks(false). In this case, adding @Leaks(false) makes the test fail, and what you probably want to do is change the implementation until the test passes with @Leaks(false). It is also possible to test that a leak prevention workaround will allow the classloader to be garbage collected by using the @LeakPreventor annotation. So in case you intend to add some cleanup method that needs to be explicitly called, you should create a Runnable that calls the cleanup method, and annotate the test class with @LeakPreventor(MyCleanupRunnable.class) Just get back to me if you need further instructions!
        Hide
        Manfred Riem added a comment -

        Applied to 2.2 branch,

        svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2746, make sure the data structure is kept within the ServletContext."
        Sending jsf-api/src/main/java/javax/faces/component/UIComponentBase.java
        Sending jsf-api/src/test/java/javax/faces/component/ValueHolderTestCaseBase.java
        Transmitting file data ..
        Committed revision 12591.

        Show
        Manfred Riem added a comment - Applied to 2.2 branch, svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2746 , make sure the data structure is kept within the ServletContext." Sending jsf-api/src/main/java/javax/faces/component/UIComponentBase.java Sending jsf-api/src/test/java/javax/faces/component/ValueHolderTestCaseBase.java Transmitting file data .. Committed revision 12591.
        Hide
        Manfred Riem added a comment -

        Applied to 2.2 branch,

        svn commit -m "Reverting #2746 and investigating failures"
        Sending jsf-api/src/main/java/javax/faces/component/UIComponentBase.java
        Transmitting file data .
        Committed revision 12592.

        Show
        Manfred Riem added a comment - Applied to 2.2 branch, svn commit -m "Reverting #2746 and investigating failures" Sending jsf-api/src/main/java/javax/faces/component/UIComponentBase.java Transmitting file data . Committed revision 12592.
        Hide
        Manfred Riem added a comment -

        Changes to the JUnit tests to accomodate for changes in UIComponentBase.

        Show
        Manfred Riem added a comment - Changes to the JUnit tests to accomodate for changes in UIComponentBase.
        Hide
        Manfred Riem added a comment -

        Applied to 2.2 branch,

        svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2746, make sure the descriptor map is stored in the servlet context."
        Sending jsf-api/src/main/java/javax/faces/component/UIComponentBase.java
        Sending test/unit/src/test/java/javax/faces/component/UIParameterTest.java
        Sending test/unit/src/test/java/javax/faces/component/UIViewRootTest.java
        Transmitting file data ...
        Committed revision 12593.

        Show
        Manfred Riem added a comment - Applied to 2.2 branch, svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2746 , make sure the descriptor map is stored in the servlet context." Sending jsf-api/src/main/java/javax/faces/component/UIComponentBase.java Sending test/unit/src/test/java/javax/faces/component/UIParameterTest.java Sending test/unit/src/test/java/javax/faces/component/UIViewRootTest.java Transmitting file data ... Committed revision 12593.

          People

          • Assignee:
            Manfred Riem
            Reporter:
            Mattias Jiderhamn
          • Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: