Wicket
  1. Wicket
  2. WICKET-1365

Having instance variables referencing pages causes memory leaks, StackOverflowErrors and ClassCastExceptions

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.3.1
    • Fix Version/s: 1.3.2
    • Component/s: wicket
    • Labels:
      None

      Description

      Having references (instance variables), in objects reachable from the component hierarchy, to pages other than the "current" page, causes memory leaks StackOverflowErrors and sometimes ClassCastExceptions.

      This seems to be due to the special serialization code implemented in Page, even if I haven't been able to pinpoint exactly where the problem lies. Standard serialization handles cycles between objects if the deserialization or serialization is done using the same ObjectInputStream or ObjectOutputStream, but here each Page is being deserialized in different ObjectInputStreams.

      Looking at the stack traces from the StackOverflowErrors it's easy to see that it's the deserialization that goes over the same pages over and over again (although it's new instances).

      The ClassCastExceptions where because the Page.numericId was zero when serializing them in Page.writeObject, causing the wrong Page to be deserialized in readObject. By looking at the code I can't really understand how the numericId can become zero, except for in the first page. The only thing I can think of is if it's being serialized by another thread before it's initialized.

      Our application is "AJAX only" with a main page built up of quite a lot of components in a quite deep hierarchy. When discovering this problem, there was one panel with seven different AjaxLinks that opened ModalWindows, where some of the ModalWindows had fields referencing the contained iframe pages. Clicking around on the links soon made the memory and CPU consumption rise and after a while one of the mentioned errors occurred.

      Even if I thought that it would, neither turning off page versioning nor setting ISessionSettings.setPageIdUniquePerSession(true) seemed to have any effect.

      After redesigning the code a bit, removing all the field references to Pages, it seems to work fine again. I realize that having such references isn't a very good design even without this problem. Perhaps it shouldn't be supported at all. It might be, though, that some users have done this and don't know it's a problem (yet).

      Although in the above case it was only AJAX, I've made an example application that also shows that the same problems occurs using normal links, and pages with references between them. I'll attach that example in a couple of minutes.

      1. ModalWindowTest.zip
        51 kB
        Henrik Lundahl

        Activity

        Hide
        Henrik Lundahl added a comment -

        Just click around on the links and soon you'll get an OutOfMemoryError. If you increase the maximum heap size you'll likely get a StackOverflowError.

        As you can see in the code, I've added som large objects. This is just to decrease the number of clicks needed before the errors occur. It seems that the problem gets much worse when you have a deep and wide component hierarchy.

        Show
        Henrik Lundahl added a comment - Just click around on the links and soon you'll get an OutOfMemoryError. If you increase the maximum heap size you'll likely get a StackOverflowError. As you can see in the code, I've added som large objects. This is just to decrease the number of clicks needed before the errors occur. It seems that the problem gets much worse when you have a deep and wide component hierarchy.
        Hide
        Matej Knopp added a comment -

        I've commited fix for this problem. Can you please check if it fixes the OOM for you?

        Show
        Matej Knopp added a comment - I've commited fix for this problem. Can you please check if it fixes the OOM for you?
        Hide
        Henrik Lundahl added a comment -

        I'm sorry, but I hardly notice any difference. Have you tested with the quick-start example I've attached?

        Show
        Henrik Lundahl added a comment - I'm sorry, but I hardly notice any difference. Have you tested with the quick-start example I've attached?
        Hide
        Matej Knopp added a comment -

        Hi,

        of course I have. I can't get the OOM now (it was very simple before the fix). Can you please make sure that you are running the quickstart with latest trunk and that you don't have the old snapshots somewhere in your classpath? Also I'm not sure if the current snapshot contains the fix (though it should).

        Show
        Matej Knopp added a comment - Hi, of course I have. I can't get the OOM now (it was very simple before the fix). Can you please make sure that you are running the quickstart with latest trunk and that you don't have the old snapshots somewhere in your classpath? Also I'm not sure if the current snapshot contains the fix (though it should).
        Hide
        Henrik Lundahl added a comment -

        I checked out the latest code from http://svn.apache.org/repos/asf/wicket/trunk, added a log statement in org.apache.wicket.Page.writeReplace (which didn't exist before the fix), installed it into my maven repository, ran the test project using first jetty and then tomcat and verified that the log statement was printed. I still get OOME by the seventh or eighth AJAX link click (with -Xmx64M). Do you have any ideas on what I can have overlooked here?

        Show
        Henrik Lundahl added a comment - I checked out the latest code from http://svn.apache.org/repos/asf/wicket/trunk , added a log statement in org.apache.wicket.Page.writeReplace (which didn't exist before the fix), installed it into my maven repository, ran the test project using first jetty and then tomcat and verified that the log statement was printed. I still get OOME by the seventh or eighth AJAX link click (with -Xmx64M). Do you have any ideas on what I can have overlooked here?
        Hide
        Matej Knopp added a comment -

        Actually, I can still reproduce the OOM with the modal window test, though the non-ajax stuff works ok for me. I'll take a look at it.

        Show
        Matej Knopp added a comment - Actually, I can still reproduce the OOM with the modal window test, though the non-ajax stuff works ok for me. I'll take a look at it.
        Hide
        Matej Knopp added a comment -

        Actually, this one was not related to the first OOM problem. This was just a DiskPageStore cache getting OOM. I've fixed that by using SoftReferences. You wouldn't probably encounter this one in production, as it would only happen with very small heap size (like the 64M)

        Can you please check if the problem is fixed for you?

        Show
        Matej Knopp added a comment - Actually, this one was not related to the first OOM problem. This was just a DiskPageStore cache getting OOM. I've fixed that by using SoftReferences. You wouldn't probably encounter this one in production, as it would only happen with very small heap size (like the 64M) Can you please check if the problem is fixed for you?
        Hide
        Henrik Lundahl added a comment -

        It's fixed. Great job! Thanks!

        Show
        Henrik Lundahl added a comment - It's fixed. Great job! Thanks!

          People

          • Assignee:
            Matej Knopp
            Reporter:
            Henrik Lundahl
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development