2017-06-08 5 views
6

J'écris un IntelliJ-Plugin pour analyser le code du programme java. Ainsi, j'utilise Soot pour écrire des analyses statiques. Chaque fois qu'un utilisateur déclenche l'action de mon analyse plug-in, je prends la VirtualFile actuelle du contexte actuel comme celui-ci:Soot: Recharger la classe après le changement du fichier source

FileEditorManager manager = FileEditorManager.getInstance(e.getProject()); 
VirtualFile files[] = manager.getSelectedFiles(); 
toAnalyse = files[0]; [...] 

Quand je vérifie le contenu de ce fichier toutes les modifications sont appliquées. Après cela, je charge la classe que je veux analyser dans Soot.

String dir = toAnalyse.getParent().getPath() ; 
Options.v().setPhaseOption("jb", "use-original-names"); 
Options.v().set_soot_classpath(System.getProperty("java.home")+";"+ dir); 
c = Scene.v().loadClassAndSupport(name); 
/*no analyse c*/ 

Cela fonctionne parfaitement pour moi. Mais maintenant à mon problème: Si je change sth. dans l'instance de test de mon plugin et déclencher à nouveau la même analyse, rien ne change.

Qu'ai-je essayé jusqu'à présent?

I défini les options suivantes:

Options.v().set_dump_body(Arrays.asList("jb")); 
Options.v().set_dump_cfg(Arrays.asList("jb")); 
Options.v().set_allow_phantom_refs(true); 
Options.v().set_whole_program(true); 

J'ai aussi enlevé toutes les classes à la main

comme ceci:

Chain<SootClass> classes = Scene.v().getClasses(); 
Stack<SootClass> stack = new Stack<>(); 
for(SootClass s : classes) 
    stack.push(s); 
while(!stack.empty()) 
    Scene.v().removeClass(stack.pop()); 

et a commencé à nouveau le programme.

Répondre

5

J'ai résolu ce problème.

SootClass c = Scene.v().loadClassAndSupport(name); 
// ... 
c.setResolvingLevel(0); 
G.reset(); 

G.reset() remet à zéro toutes les instances singleton. Par conséquent, tous les résultats mis en cache seront remplacés en appelant à nouveau cette action.

public static Scene v() { 
    return G.v().soot_Scene(); 
} 

this.instance_soot_Scene est null après avoir appelé G.reset().

Par conséquent, le code suivant:

public Scene soot_Scene() { 
    if(this.instance_soot_Scene == null) { 
     synchronized(this) { 
      if(this.instance_soot_Scene == null) { 
       this.instance_soot_Scene = new Scene(this.g); 
      } 
     } 
    } 

    return this.instance_soot_Scene; 
} 

retourne une nouvelle instance avec un cache de résultats vide.