I am running in circles:

If I keep using the map from the Spring Framework, but with a soft reference instead of a weak reference inside, things get (of course) only softly-collectable classes and performance degrades somewhat, becomes almost identical to the current implementation (2.5.0 master).

If I use a WeakHashMap or Collections.synchronizedMap(WeakHashMap) instead of the map from the Spring Framework, classes are not collectable in the script-running-use-case (OutOfMemoryError) unless I replace klazz in ClassInfo with a WeakRefererence and then it becomes (only) softly-collectable.

All in all, I think this means that universally weakly-collectable Groovy classes are more of a dream at the moment, at least before a Groovy 3, and the merge requests for GROOVY-7683 (weak reference to Class in ClassInfo) and GROOVY-7646 (explicit cleanup after running scripts in GroovyShell) seem to be the best that can be done at the moment?

Maybe let time find a solution...

Alain

PS: Just for fun, I wrote a version where the map from the Spring Framework is using soft references for java.*/javax.*/groovy.*/org.codehaus.groovy.* classes and weak references for all others, and that passed all my test scripts.


On 28.05.16 20:34, Alain Stalder wrote:
On 28.05.16 19:38, Alain Stalder wrote:
Hmn, not sure yet, but looks like the map from the Spring Framework I am using is treating both keys (Class) and values (ClassInfo) as weak references, not sure yet if this could easily be changed...

No, at least no indication of that so far, seems only to determine ClassInfo once per class.

Yes, that is the issue, map entries can be garbage collected even if the class is still loaded (e.g. Integer)...

e.g.

def scriptText = """
class Script1 extends Script {
   static class Inner {
       int x = 1;
   }

   Object run() {
       print "."
       return new Inner().x + new Parallel().y
       return x+y
   }
}

class Parallel {
    int y = 2;
}
"""

def shell = new GroovyShell()
//for (int i=0; i<1000; i++) {
//   long t0 = System.nanoTime()
   for (int j=0; j<1000; j++) {
      shell.run(scriptText, "script", [])
   }
//   long t1 = System.nanoTime()
//   printf("%3d: %3.1fs%n", i, ((double)(t1-t0))/1000000000)
//}

=>

Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: java.lang.Integer.plus() is applicable for argument types: (java.lang.Integer) values: [2] Possible solutions: sum(int, int), wait(), equals(java.lang.Object), wait(long), wait(long, int), equals(java.lang.Object)



Reply via email to