Skip to content

Instantly share code, notes, and snippets.

@jsmucr
Created June 29, 2022 05:42
Show Gist options
  • Select an option

  • Save jsmucr/e3c36fd3393fc1345ad3dfa711b46960 to your computer and use it in GitHub Desktop.

Select an option

Save jsmucr/e3c36fd3393fc1345ad3dfa711b46960 to your computer and use it in GitHub Desktop.

Revisions

  1. jsmucr created this gist Jun 29, 2022.
    22 changes: 22 additions & 0 deletions LeakDynamic.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    import groovy.lang.GroovyClassLoader;

    class LeakDynamic {

    public static interface TestClass {
    String getThingy();
    }

    static String getTheThingy() {
    return "the thingy";
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws Exception {
    for (int i = 0; i < 1000; i++) {
    var cl = new GroovyClassLoader();
    var c = cl.parseClass("class TestClass" + i + " implements LeakDynamic.TestClass { public String getThingy() { return LeakDynamic.getTheThingy(); } }");
    var t = (TestClass) c.getConstructor().newInstance();
    assert t.getThingy() == getTheThingy();
    }
    }
    }
    22 changes: 22 additions & 0 deletions LeakStatic.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    import groovy.lang.GroovyClassLoader;

    class LeakStatic {

    public static interface TestClass {
    String getThingy();
    }

    static String getTheThingy() {
    return "the thingy";
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws Exception {
    for (int i = 0; i < 1000; i++) {
    var cl = new GroovyClassLoader();
    var c = cl.parseClass("class TestClass" + i + " implements LeakStatic.TestClass { @groovy.transform.CompileStatic public String getThingy() { return LeakStatic.getTheThingy(); } }");
    var t = (TestClass) c.getConstructor().newInstance();
    assert t.getThingy() == getTheThingy();
    }
    }
    }
    10 changes: 10 additions & 0 deletions test-dynamic.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    #!/bin/sh

    sdk install groovy 3.0.11

    javac -cp ~/.sdkman/candidates/groovy/3.0.11/lib/groovy-3.0.11.jar LeakDynamic.java

    # Lowering the heap to 16 MiB is still OK.
    export JAVA_OPTS="-Xmx32M -XX:+HeapDumpOnOutOfMemoryError -Xlog:class+unload=info"
    # Way faster than with CompileStatic.
    time java $JAVA_OPTS -cp ~/.sdkman/candidates/groovy/3.0.11/lib/groovy-3.0.11.jar:. LeakDynamic
    10 changes: 10 additions & 0 deletions test-static.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    #!/bin/sh

    sdk install groovy 3.0.11

    javac -cp ~/.sdkman/candidates/groovy/3.0.11/lib/groovy-3.0.11.jar LeakStatic.java

    # Lowering the heap to 16 MiB leads to OOM.
    export JAVA_OPTS="-Xmx32M -XX:+HeapDumpOnOutOfMemoryError -Xlog:class+unload=info"
    # Way faster than without CompileStatic.
    time java $JAVA_OPTS -cp ~/.sdkman/candidates/groovy/3.0.11/lib/groovy-3.0.11.jar:. LeakStatic