2017-10-05 3 views
2

Comme par ref-doc:Groovy: re-compiler une classe de fichiers et les fuites mémoire

A GroovyClassLoader conserve une référence de toutes les classes qu'il a créées, il est donc facile de créer une fuite de mémoire. En particulier, si vous exécutez le même script deux fois, s'il s'agit d'une chaîne, alors vous obtenez deux classes distinctes!

J'utilise un fichier comme source pour l'analyse syntaxique, mais se sont mise en cache hors:

GroovyCodeSource src = new GroovyCodeSource(file) 
    src.cachable = false 
    Class clazz = groovyClassLoader.parseClass src 
    Class clazz1 = groovyClassLoader.parseClass src 
    log.info "$clazz <=> $clazz1 equal: ${clazz == clazz1}" 

la sortie du journal est toujours

classe MyClass < => classe MyClass égale: false

Si je commente la ligne src.cachable = false, alors les instances de classe deviennent moi égal, mais ils ne re-compilent pas même si le fichier sous-jacent a changé.

D'où la question suivante: comment recompiler des classes correctement sans créer de fuite de mémoire?

Répondre

0

Après avoir fait quelques expériences, je compris que le passage de retour à l'aide de cordes:

String src = 'class A {}' 
Class clazz = groovyClassLoader.parseClass src 
log.info groovyClassLoader.loadedClasses.join(', ') 

les classes chargées ne changent pas en longueur, même si une classe a des fermetures à l'intérieur (qui apparaissent aussi comme des classes).

1

J'ai effectué le test suivant et je ne vois aucune fuite de mémoire.

quant à moi, le travail GC normal.

Le lien vers votre classe sera actif tant qu'une instance de classe sera active.

GroovyCodeSource src = new GroovyCodeSource('println "hello world"', 'Test', '/') 
src.cachable = false 

def cl=this.getClass().getClassLoader() 

for(int i=0;i<1000000;i++){ 
    Class clazz = cl.parseClass src 
    if(i%10000==0)println "$i :: $clazz :: ${System.identityHashCode(clazz)}" 
} 

enter image description here