OpenJPA
  1. OpenJPA
  2. OPENJPA-2330

Stackoverflow due to endless recursive calls

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.2.0, 2.2.1
    • Fix Version/s: 2.1.2, 2.2.1.1, 2.2.3, 2.3.0
    • Component/s: validation
    • Labels:
      None

      Description

      We wish to report another bug that generates a memory overflow resulting in an infinite recursive loop. Here are two stacktraces apparently from the same bug:

      First stacktrace sample :
      ================================================
      Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
      at java.util.LinkedHashMap$KeyIterator.<init>(LinkedHashMap.java:383)
      at java.util.LinkedHashMap$KeyIterator.<init>(LinkedHashMap.java:383)
      at java.util.LinkedHashMap.newKeyIterator(LinkedHashMap.java:396)
      at java.util.HashMap$KeySet.iterator(HashMap.java:874)
      at java.util.HashSet.iterator(HashSet.java:153)
      at org.apache.openjpa.util.java$util$LinkedHashSet$proxy.iterator(Unknown Source)
      at java.util.AbstractCollection.toArray(AbstractCollection.java:120)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedCollection(OpenJPAPersistenceUtil.java:240)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:212)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedArray(OpenJPAPersistenceUtil.java:265)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedCollection(OpenJPAPersistenceUtil.java:242)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:212)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:223)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:223)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedArray(OpenJPAPersistenceUtil.java:265)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedCollection(OpenJPAPersistenceUtil.java:242)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:212)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:223)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      [...]

      Second stacktrace sample :
      ================================================
      Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
      at java.util.HashMap$EntrySet.size(HashMap.java:963)
      at org.apache.openjpa.util.ProxyMaps$ProxyEntrySetImpl.size(ProxyMaps.java:255)
      at java.util.AbstractCollection.toArray(AbstractCollection.java:119)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedMap(OpenJPAPersistenceUtil.java:288)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:215)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedArray(OpenJPAPersistenceUtil.java:265)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedCollection(OpenJPAPersistenceUtil.java:242)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:212)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedArray(OpenJPAPersistenceUtil.java:265)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedCollection(OpenJPAPersistenceUtil.java:242)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:212)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:223)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoadedField(OpenJPAPersistenceUtil.java:223)
      at org.apache.openjpa.persistence.OpenJPAPersistenceUtil.isLoaded(OpenJPAPersistenceUtil.java:161)
      [...]

      1. openjpa-2330.jar
        11 kB
        Rick Curtis
      2. OPENJPA-2330.zip
        7 kB
        Guillaume Chauvet

        Activity

        Hide
        Kevin Sutter added a comment -

        Hi,
        Can you give some more details on your environment and the scenario that is causing this failure? I can see where it looks like a potential issue with the PersistenceUtils, but what was the user scenario that got you into this mess? We have some tests (junit, functional, cts) that utilize the PersistenceUtils. We would need some more information, preferably a junit, in order to recreate the error. Thanks!

        Show
        Kevin Sutter added a comment - Hi, Can you give some more details on your environment and the scenario that is causing this failure? I can see where it looks like a potential issue with the PersistenceUtils, but what was the user scenario that got you into this mess? We have some tests (junit, functional, cts) that utilize the PersistenceUtils. We would need some more information, preferably a junit, in order to recreate the error. Thanks!
        Hide
        Guillaume Chauvet added a comment -

        Hello,

        So sorry I was not able to provide you with more detailed information from the start, but unfortunately I didn't have the time yesterday as we are approaching deadline for release of new software.
        I am working on creating a unit test, however I will not be able to provide it straight away as I haven't been able to reproduce the bug, even though our software crashes systematically.
        So I think I will first create a patch for our version of OpenJPA to rectify the problem, then generate the unit test(s), as with the last bug report I made.

        The environment we use is OpenJPA 2.2.1 in a thick client Swing (JRE 1.6_39 64 bits). We operate an Apache Derby 10.8.2.2 database in client/server mode.
        Belowlisted the scenario in which the problematic memory overflow occurs in our application:

        Prerequisites:
        ==========

        • 3 classes of entities "EntityA", "EntityB", "EntityC"
        • bidirectional navigation between classes:
        • Cardinality OneToMany between EntityA and EntityB with the following parameters: fetch = FetchType.EAGER, mappedBy = "entitya", orphanRemoval = true, cascade = CascadeType.ALL
        • Cardinality OneToMany between EntityB and EntityC with the following parameters: fetch = FetchType.EAGER, mappedBy = "entityb", orphanRemoval = true, cascade = CascadeType.ALL
        • EntityC is associated with alot of other tables, which I won't list for now.

        Parameterization of OpenJPA:
        ==========
        <properties>
        <property name="openjpa.InverseManager" value="true"/>
        <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
        <property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/>
        <property name="openjpa.jdbc.MappingDefaults" value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/>
        <property name="openjpa.Multithreaded" value="true"/>
        <property name="openjpa.MaxFetchDepth" value="1"/>
        <property name="openjpa.NontransactionalWrite" value="true"/>
        <property name="openjpa.FetchBatchSize" value="0"/>
        </properties

        Initial state:
        ==========
        The data base already contains an entities tree depth level 3 organized as follows:

        • 2 instances of type "EntityA" type : A1, A2
        • 2 instances of "EntityB" type : B1, B2
        • 3 instances of "EntityC" type : C1, C2, C3

        -> Representation of the entity linking
        A1 -> [B1 -> [C1, C2]]
        A2 -> [B2 -> [C3]]

        Scenario:
        =================
        1) 2 new instances of EntityC "C4" & "C5" type occurrences are inserted into entity B2:

        • State of the graph following insertion:
          A1 -> [B1 -> [C1, C2]]
          A2 -> [B2 -> [C3, C4, C5]]

        2) Only entities A1 & A2 are persisted in two consecutive transactions.
        => First persist on entity A1

        • State of the graph following commit:
          A1 -> [B1 -> [C1, C2]]
          A2 -> [B2 -> []] => C3 was deleted during the first persist (new problem which we hadn't remarked yesterday).

        => Second persist on entity A2

        • State of the graph following insertion:
          A1 -> [B1 -> [C1, C2]]
          A2 -> [B2 -> [C4, C5]] => Memory overflow, causing loss of entities C4, C5.
          Urgent solution
          =================
          We are going to create a homemade corrective patch in order to mark the relations crossed between entities in the «OpenJPAPersistenceUtil » class in order to avoid all looping.
        Show
        Guillaume Chauvet added a comment - Hello, So sorry I was not able to provide you with more detailed information from the start, but unfortunately I didn't have the time yesterday as we are approaching deadline for release of new software. I am working on creating a unit test, however I will not be able to provide it straight away as I haven't been able to reproduce the bug, even though our software crashes systematically. So I think I will first create a patch for our version of OpenJPA to rectify the problem, then generate the unit test(s), as with the last bug report I made. The environment we use is OpenJPA 2.2.1 in a thick client Swing (JRE 1.6_39 64 bits). We operate an Apache Derby 10.8.2.2 database in client/server mode. Belowlisted the scenario in which the problematic memory overflow occurs in our application: Prerequisites: ========== 3 classes of entities "EntityA", "EntityB", "EntityC" bidirectional navigation between classes: Cardinality OneToMany between EntityA and EntityB with the following parameters: fetch = FetchType.EAGER, mappedBy = "entitya", orphanRemoval = true, cascade = CascadeType.ALL Cardinality OneToMany between EntityB and EntityC with the following parameters: fetch = FetchType.EAGER, mappedBy = "entityb", orphanRemoval = true, cascade = CascadeType.ALL EntityC is associated with alot of other tables, which I won't list for now. Parameterization of OpenJPA: ========== <properties> <property name="openjpa.InverseManager" value="true"/> <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/> <property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/> <property name="openjpa.jdbc.MappingDefaults" value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/> <property name="openjpa.Multithreaded" value="true"/> <property name="openjpa.MaxFetchDepth" value="1"/> <property name="openjpa.NontransactionalWrite" value="true"/> <property name="openjpa.FetchBatchSize" value="0"/> </properties Initial state: ========== The data base already contains an entities tree depth level 3 organized as follows: 2 instances of type "EntityA" type : A1, A2 2 instances of "EntityB" type : B1, B2 3 instances of "EntityC" type : C1, C2, C3 -> Representation of the entity linking A1 -> [B1 -> [C1, C2] ] A2 -> [B2 -> [C3] ] Scenario: ================= 1) 2 new instances of EntityC "C4" & "C5" type occurrences are inserted into entity B2: State of the graph following insertion: A1 -> [B1 -> [C1, C2] ] A2 -> [B2 -> [C3, C4, C5] ] 2) Only entities A1 & A2 are persisted in two consecutive transactions. => First persist on entity A1 State of the graph following commit: A1 -> [B1 -> [C1, C2] ] A2 -> [B2 -> []] => C3 was deleted during the first persist (new problem which we hadn't remarked yesterday). => Second persist on entity A2 State of the graph following insertion: A1 -> [B1 -> [C1, C2] ] A2 -> [B2 -> [C4, C5] ] => Memory overflow, causing loss of entities C4, C5. Urgent solution ================= We are going to create a homemade corrective patch in order to mark the relations crossed between entities in the «OpenJPAPersistenceUtil » class in order to avoid all looping.
        Hide
        Rick Curtis added a comment -

        I see that you are using two properties that are known to cause headaches...

        • openjpa.RuntimeUnenhancedClasses – has many known bugs and I highly recommend using another enhancement strategy. I'd wager a guess that using buildtime enhacement has a good chance of fixing this StackOverflowError.
        • openjpa.Multithreaded, also has a number of known issues and if you're seeing intermittent deadlocks, it is due to the usage of this property.

        Thanks,
        Rick

        Show
        Rick Curtis added a comment - I see that you are using two properties that are known to cause headaches... openjpa.RuntimeUnenhancedClasses – has many known bugs and I highly recommend using another enhancement strategy. I'd wager a guess that using buildtime enhacement has a good chance of fixing this StackOverflowError. openjpa.Multithreaded, also has a number of known issues and if you're seeing intermittent deadlocks, it is due to the usage of this property. Thanks, Rick
        Hide
        Guillaume Chauvet added a comment -

        I use the buildtime enhancement strategy now. I noticed that I no longer random clob/blob error anymore in another part of the software, after removing the two OpenJPA properties (thanks !!).
        In contrast, I've always the Stackoverflow error... I continue my investigation.

        Show
        Guillaume Chauvet added a comment - I use the buildtime enhancement strategy now. I noticed that I no longer random clob/blob error anymore in another part of the software, after removing the two OpenJPA properties (thanks !!). In contrast, I've always the Stackoverflow error... I continue my investigation.
        Hide
        Guillaume Chauvet added a comment -

        Hello,

        I am writing to you again as after having removed the two problematic options, I tried several times but the problem was not at all resolved.
        I am however obliged to retain the openjpa.Multithreaded property, given that we use swingworkers in another part of the software; otherwise a competitive access provider exception occurs.

        Attached (finally!) please find a draft including a unit test capable of systematically reproducing the error.

        Show
        Guillaume Chauvet added a comment - Hello, I am writing to you again as after having removed the two problematic options, I tried several times but the problem was not at all resolved. I am however obliged to retain the openjpa.Multithreaded property, given that we use swingworkers in another part of the software; otherwise a competitive access provider exception occurs. Attached (finally!) please find a draft including a unit test capable of systematically reproducing the error.
        Hide
        Guillaume Chauvet added a comment -

        oops, please downgrade openjpa-all version from 2.2.2-QFD to 2.2.1

        Show
        Guillaume Chauvet added a comment - oops, please downgrade openjpa-all version from 2.2.2-QFD to 2.2.1
        Hide
        Rick Curtis added a comment -

        I wasn't able to figure out the root problem yet, but it appears that it has something to do with the interaction between OpenJPA and Apache BeanValidation. If you're not using bv, a workaround for the meantime would be to set <validation-mode> to NONE. Hopefully I'll get some more time next week to continue digging into this issue.

        Thanks,
        Rick

        <persistence-unit name="OPENJPA2330" transaction-type="RESOURCE_LOCAL">
        <class>com.qualiformed.openjpa.jira2330.entity.AbstractEntityC</class>
        <class>com.qualiformed.openjpa.jira2330.entity.EntityA</class>
        <class>com.qualiformed.openjpa.jira2330.entity.EntityB</class>
        <class>com.qualiformed.openjpa.jira2330.entity.EntityC</class>
        <validation-mode>NONE</validation-mode>
        <properties>

        Show
        Rick Curtis added a comment - I wasn't able to figure out the root problem yet, but it appears that it has something to do with the interaction between OpenJPA and Apache BeanValidation. If you're not using bv, a workaround for the meantime would be to set <validation-mode> to NONE. Hopefully I'll get some more time next week to continue digging into this issue. Thanks, Rick <persistence-unit name="OPENJPA2330" transaction-type="RESOURCE_LOCAL"> <class>com.qualiformed.openjpa.jira2330.entity.AbstractEntityC</class> <class>com.qualiformed.openjpa.jira2330.entity.EntityA</class> <class>com.qualiformed.openjpa.jira2330.entity.EntityB</class> <class>com.qualiformed.openjpa.jira2330.entity.EntityC</class> <validation-mode>NONE</validation-mode> <properties>
        Hide
        Rick Curtis added a comment -

        Please try to test fix that I've attached here. This fix is based off trunk, and it should work on 2.2.x, but let me know if it doesn't work. You can either lay this class on top of your existing openjpa jar, or you can preprend it to your classpath. Let me know how it goes.

        Your other option is to pull the patch out of the jar, and build your own fix based off your version of OpenJPA.

        Show
        Rick Curtis added a comment - Please try to test fix that I've attached here. This fix is based off trunk, and it should work on 2.2.x, but let me know if it doesn't work. You can either lay this class on top of your existing openjpa jar, or you can preprend it to your classpath. Let me know how it goes. Your other option is to pull the patch out of the jar, and build your own fix based off your version of OpenJPA.
        Hide
        Guillaume Chauvet added a comment -

        Hi Rick,

        Your patch works perfectly, however I still have the loss of a node in the tree.
        I will now open a new ticket with the unit test (which is an extension of the one provided in this ticket).

        Show
        Guillaume Chauvet added a comment - Hi Rick, Your patch works perfectly, however I still have the loss of a node in the tree. I will now open a new ticket with the unit test (which is an extension of the one provided in this ticket).
        Hide
        ASF subversion and git services added a comment -

        Commit 1448662 from curtisr7
        [ https://svn.apache.org/r1448662 ]

        OPENJPA-2330: Fix StackoverflowError when checking if a field is loaded. Test contributed by Guillaume Chauvet.

        Show
        ASF subversion and git services added a comment - Commit 1448662 from curtisr7 [ https://svn.apache.org/r1448662 ] OPENJPA-2330 : Fix StackoverflowError when checking if a field is loaded. Test contributed by Guillaume Chauvet.
        Hide
        Rick Curtis added a comment -

        Committed revision 1448662 to trunk. Thanks for the UT Guillaume!

        Show
        Rick Curtis added a comment - Committed revision 1448662 to trunk. Thanks for the UT Guillaume!
        Hide
        ASF subversion and git services added a comment -

        Commit 1448796 from curtisr7
        [ https://svn.apache.org/r1448796 ]

        OPENJPA-2330: Change test Entity names.

        Show
        ASF subversion and git services added a comment - Commit 1448796 from curtisr7 [ https://svn.apache.org/r1448796 ] OPENJPA-2330 : Change test Entity names.
        Hide
        ASF subversion and git services added a comment -

        Commit 1531176 from Heath Thomann in branch 'openjpa/branches/2.2.1.x'
        [ https://svn.apache.org/r1531176 ]

        OPENJPA-2330: Stackoverflow due to endless recursive calls - back ported to 2.2.1.x Rick Cutis's changes to trunk.

        Show
        ASF subversion and git services added a comment - Commit 1531176 from Heath Thomann in branch 'openjpa/branches/2.2.1.x' [ https://svn.apache.org/r1531176 ] OPENJPA-2330 : Stackoverflow due to endless recursive calls - back ported to 2.2.1.x Rick Cutis's changes to trunk.
        Hide
        ASF subversion and git services added a comment -

        Commit 1531177 from Heath Thomann in branch 'openjpa/branches/2.2.x'
        [ https://svn.apache.org/r1531177 ]

        OPENJPA-2330: Stackoverflow due to endless recursive calls - back ported to 2.2.x Rick Cutis's changes to trunk.

        Show
        ASF subversion and git services added a comment - Commit 1531177 from Heath Thomann in branch 'openjpa/branches/2.2.x' [ https://svn.apache.org/r1531177 ] OPENJPA-2330 : Stackoverflow due to endless recursive calls - back ported to 2.2.x Rick Cutis's changes to trunk.
        Hide
        ASF subversion and git services added a comment -

        Commit 1539086 from Heath Thomann in branch 'openjpa/branches/2.1.x'
        [ https://svn.apache.org/r1539086 ]

        OPENJPA-2330: Stackoverflow due to endless recursive calls - back ported to 2.1.x Rick Cutis's changes to trunk.

        Show
        ASF subversion and git services added a comment - Commit 1539086 from Heath Thomann in branch 'openjpa/branches/2.1.x' [ https://svn.apache.org/r1539086 ] OPENJPA-2330 : Stackoverflow due to endless recursive calls - back ported to 2.1.x Rick Cutis's changes to trunk.

          People

          • Assignee:
            Rick Curtis
            Reporter:
            Guillaume Chauvet
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development