J'ai besoin d'écrire un outil qui répertorie les classes qui appellent des méthodes d'interfaces spécifiées. Il sera utilisé dans le cadre du processus de construction d'une grande application Java composée de nombreux modules. L'objectif est de documenter automatiquement les dépendances entre certains modules Java.Est-ce que la méthode ASM-visiteurs peut être utilisée avec des interfaces?
J'ai trouvé plusieurs outils pour l'analyse des dépendances, mais ils ne fonctionnent pas au niveau de la méthode, uniquement pour les packages ou les jars. Enfin, j'ai trouvé ASM, qui semble faire ce dont j'ai besoin.
Le code suivant imprime les dépendances de la méthode de tous les fichiers de classe dans un répertoire donné:
import java.io.*;
import java.util.*;
import org.objectweb.asm.ClassReader;
public class Test {
public static void main(String[] args) throws Exception {
File dir = new File(args[0]);
List<File> classFiles = new LinkedList<File>();
findClassFiles(classFiles, dir);
for (File classFile : classFiles) {
InputStream input = new FileInputStream(classFile);
new ClassReader(input).accept(new MyClassVisitor(), 0);
input.close();
}
}
private static void findClassFiles(List<File> list, File dir) {
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
findClassFiles(list, file);
} else if (file.getName().endsWith(".class")) {
list.add(file);
}
}
}
}
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.EmptyVisitor;
public class MyClassVisitor extends EmptyVisitor {
private String className;
@Override
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
this.className = name;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
System.out.println(className + "." + name);
return new MyMethodVisitor();
}
}
import org.objectweb.asm.commons.EmptyVisitor;
public class MyMethodVisitor extends EmptyVisitor {
@Override
public void visitMethodInsn(int opcode, String owner, String name,
String desc) {
String key = owner + "." + name;
System.out.println(" " + key);
}
}
Le problème:
Le code fonctionne pour les classes régulières seulement! Si le fichier de classe contient une interface, visitMethod est appelée, mais pas visitMethodInsn. Je ne reçois aucune information sur les appelants des méthodes d'interface.
Des idées?
Je ne pense pas qu'avoir un corps de méthode est pertinent dans ce cas. La méthode d'interface est visitée parce que * visitMethod() * est appelée et une nouvelle instance * MyMethodVisitor * est renvoyée, mais ce * MyMethodVisitor * semble être ignoré par la suite. Je lis les classes à partir du disque, car j'ai besoin d'analyser une application qui n'est pas en cours d'exécution. –