Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-7591

Use of ClassValue causes major memory leak

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.4.0, 2.4.1, 2.4.2, 2.4.3, 2.4.4
    • Fix Version/s: 2.4.5
    • Component/s: None
    • Labels:
      None

      Description

      Following the discussion at http://mail-archives.apache.org/mod_mbox/incubator-groovy-dev/201509.mbox/%3CCADQzvm%3DvCHR7c1-uaCMkEq7i58ofvvaUrnqHjiGxMp0YQFuc5w%40mail.gmail.com%3E

      And the JDK bug https://bugs.openjdk.java.net/browse/JDK-8136353

      We suggest to disable use of ClassValue by default until bug is fixed in the JDK. There's a system property which will let the user reactivate use of ClassValue: groovy.use.classvalue

        Issue Links

          Activity

          Show
          candrews Craig added a comment - Relevant commit: https://github.com/apache/incubator-groovy/commit/8e9716256b95ee9a8e0c902cd49a22f4fe411137#diff-92a89f885b3969cf8ec46d4516d3abc9
          Hide
          melix Cédric Champeau added a comment -

          FWIW, even after upgrading Gradle to 2.4.5, I'm still seeing PermGen space issues which are related to the globalClassValue store (and in this case, not using ClassValue). The leak is different though, so deserves another ticket.

          Show
          melix Cédric Champeau added a comment - FWIW, even after upgrading Gradle to 2.4.5, I'm still seeing PermGen space issues which are related to the globalClassValue store (and in this case, not using ClassValue). The leak is different though, so deserves another ticket.
          Hide
          candrews Craig added a comment -

          Are you seeing GROOVY-6704 ?

          Show
          candrews Craig added a comment - Are you seeing GROOVY-6704 ?
          Hide
          blackdrag Jochen Theodorou added a comment -

          GROOVY-6704 was a different issue

          Show
          blackdrag Jochen Theodorou added a comment - GROOVY-6704 was a different issue
          Hide
          melix Cédric Champeau added a comment -

          No, it's different from GROOVY-6704. Downgrading to 2.3.11 and I don't see a leak. So it's definitely related to the changes in that area.

          Show
          melix Cédric Champeau added a comment - No, it's different from GROOVY-6704 . Downgrading to 2.3.11 and I don't see a leak. So it's definitely related to the changes in that area.
          Hide
          jexler Jex Jexler added a comment -

          This issue puzzles me, because I observe exactly the opposite when I run a script like

          while(true) new GroovyShell().parse('42')

          or

          while(true) new ConfigSlurper().parse('72')

          and limit PermGen resp. Metaspace, say, to 64m, this crashes various VMs after about a minute with an "OutOfMemoryError: PermGen space|Metaspace" in the following cases:

          • Groovy 2.4.6, groovy.use.shareclasses=false (or not set) => crash
          • Groovy 2.4.6, groovy.use.shareclasses=true => works, PermGen/Metaspace is garbage collected when it nears the configured maximum (resp. already earlier with JDK 9)
          • Groovy 2.4.4 => works, too (as expected because is implicitly using shareclasses)
          • (Groovy 2.3.9 => crash (except with JDK 9))

          VMs I tested on include Oracle JDK 1.8.0_92 on Mac, Oracle JDK 1.7.0_67 on Mac, Oracle JDK 1.8.0_51 on CentOS 6.7 (64 bit) and Oracle/OpenJDK 9-ea+116 on Debian 7 (64 bit(.

          So this behavior seems to be quite whitespread and note that "out-of-the-box" Groovy 2.4.6 fails here.

          Is this a known issue?

          Show
          jexler Jex Jexler added a comment - This issue puzzles me, because I observe exactly the opposite when I run a script like while ( true ) new GroovyShell().parse('42') or while ( true ) new ConfigSlurper().parse('72') and limit PermGen resp. Metaspace, say, to 64m, this crashes various VMs after about a minute with an "OutOfMemoryError: PermGen space|Metaspace" in the following cases: Groovy 2.4.6, groovy.use.shareclasses=false (or not set) => crash Groovy 2.4.6, groovy.use.shareclasses=true => works , PermGen/Metaspace is garbage collected when it nears the configured maximum (resp. already earlier with JDK 9) Groovy 2.4.4 => works, too (as expected because is implicitly using shareclasses) (Groovy 2.3.9 => crash (except with JDK 9)) VMs I tested on include Oracle JDK 1.8.0_92 on Mac, Oracle JDK 1.7.0_67 on Mac, Oracle JDK 1.8.0_51 on CentOS 6.7 (64 bit) and Oracle/OpenJDK 9-ea+116 on Debian 7 (64 bit(. So this behavior seems to be quite whitespread and note that "out-of-the-box" Groovy 2.4.6 fails here. Is this a known issue?
          Hide
          jexler Jex Jexler added a comment -

          Ah, I see, looks like at least these two issues are essentially the same as what I observed:

          GROOVY-7683 Memory leak when using Groovy as JSR-223 scripting language.
          GROOVY-7646 Classes generated by Eval() never collected from Permgen/Metaspace

          There was some recent action on the first one in the comments, so I guess a fix might be "around the corner"?

          I guess I will bring this to the dev list to ask for status...

          Show
          jexler Jex Jexler added a comment - Ah, I see, looks like at least these two issues are essentially the same as what I observed: GROOVY-7683 Memory leak when using Groovy as JSR-223 scripting language. GROOVY-7646 Classes generated by Eval() never collected from Permgen/Metaspace There was some recent action on the first one in the comments, so I guess a fix might be "around the corner"? I guess I will bring this to the dev list to ask for status...
          Hide
          jexler Jex Jexler added a comment -

          For completeness, the thread at the dev list: http://groovy.329449.n5.nabble.com/To-ClassValue-or-not-to-ClassValue-That-is-the-question-tp5732725.html
          Provides also test code that leaks classes the way described/fixed by this issue, with groovy.use.classvalue=true, but not with fals (the default).

          Show
          jexler Jex Jexler added a comment - For completeness, the thread at the dev list: http://groovy.329449.n5.nabble.com/To-ClassValue-or-not-to-ClassValue-That-is-the-question-tp5732725.html Provides also test code that leaks classes the way described/fixed by this issue, with groovy.use.classvalue=true, but not with fals (the default).
          Hide
          candrews Craig added a comment -

          Also, for completeness, this problem is a bug in the Oracle JRE, see https://bugs.openjdk.java.net/browse/JDK-8136353 which includes a reduced (no Groovy) test case demonstrating the bug. I contacted the OpenJDK project trying to get some attention on this issue http://mail.openjdk.java.net/pipermail/mlvm-dev/2016-January/006563.html but it appears I didn't get enough attention on it to get it fixed.

          Show
          candrews Craig added a comment - Also, for completeness, this problem is a bug in the Oracle JRE, see https://bugs.openjdk.java.net/browse/JDK-8136353 which includes a reduced (no Groovy) test case demonstrating the bug. I contacted the OpenJDK project trying to get some attention on this issue http://mail.openjdk.java.net/pipermail/mlvm-dev/2016-January/006563.html but it appears I didn't get enough attention on it to get it fixed.
          Hide
          jexler Jex Jexler added a comment -

          Also, for completeness, ClassValue (whose implementation is the issue in the JDK bug) had been introduced into the JDK specifically for use by dynamic languages like Groovy. The main description of ClassValue in Java 7 Javadoc reads: "Lazily associate a computed value with (potentially) every type. For example, if a dynamic language needs to construct a message dispatch table for each class encountered at a message send call site, it can use a ClassValue to cache information needed to perform the message send quickly, for each class encountered."

          Show
          jexler Jex Jexler added a comment - Also, for completeness, ClassValue (whose implementation is the issue in the JDK bug) had been introduced into the JDK specifically for use by dynamic languages like Groovy. The main description of ClassValue in Java 7 Javadoc reads: "Lazily associate a computed value with (potentially) every type. For example, if a dynamic language needs to construct a message dispatch table for each class encountered at a message send call site, it can use a ClassValue to cache information needed to perform the message send quickly, for each class encountered."
          Hide
          jkemnade Jochen Kemnade added a comment -

          It seems that GROOVY-7683 caused this issue after all. Shouldn't ClassValue be enabled by default again?

          Show
          jkemnade Jochen Kemnade added a comment - It seems that GROOVY-7683 caused this issue after all. Shouldn't ClassValue be enabled by default again?

            People

            • Assignee:
              melix Cédric Champeau
              Reporter:
              melix Cédric Champeau
            • Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development