dimanche 3 février 2008

BCEL

BCEL est une librairie java qui fait partie du projet apache. Cette librairie permet de manipuler, modifier des classes java ou créer des classes jva compilés (.class). On pourrait très bien à partir de cette librairie créer un compilateur pour une jvm ou rajouter un mécanisme de persistance à la volée à des pojos qui n'en possèdent pas.

Voici un petit exemple simple qui montre comment rajouter une méthode sur une classe :


import org.apache.bcel.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;

/**
* Cette classe est capable de s'automodifier Elle implémente l'interface
* Constants qui contient toutes les constantes nécessaire à bcel, y compris les
* instructions assembleurs de la jvm
*
* @author olivier THEBAULT
*
*/
public class ClassModifier implements Constants {
private JavaClass clazz;
private ClassGen classGen;
private ConstantPoolGen cp;

/**
* Constructeur
*
* @param clazz
* le nom de la classe à modifier
* @throws ClassNotFoundException
*/
public ClassModifier(String clazz) throws ClassNotFoundException {
this.clazz = Repository.lookupClass(clazz);
this.classGen = new ClassGen(this.clazz);
this.cp = this.classGen.getConstantPool();
}

/**
* main de test - la classe à modifier est ClassModifier
*
* @param args
*/
public static void main(String args[]) {

ClassModifier modifier;
try {
modifier = new ClassModifier("ClassModifier");
modifier.start();

} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

public void start() {
if (this.clazz != null) {
// on liste les méthodes de la classe avant d'en ajouter une
Method[] methods = classGen.getJavaClass().getMethods();
System.out.println("*** Avant d'ajouter une méthode ***");
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}

// la méthode à rajouter devra comporter une liste d'instructions
// dans le cas présent, cette liste est vide
InstructionList il = new InstructionList();

// on construit la nouvelle méthode, elle est publique et statique
MethodGen laMethodeARajouter = new MethodGen(ACC_PUBLIC
| ACC_STATIC,
Type.VOID, // elle retourne void
Type.NO_ARGS, // elle n'a pas de paramètres
new String[] {}, // Sa liste de nom de paramètres est de
// fait vide
"nouvelleMethode", // elle s'appelle "nouvelleMethode"
clazz.getClassName(),// c'est une méthode de la classe "clazz"
il, // sa liste d'instructions est il
cp);

// on ajoute la méthode "nouvelleMethode" à la classe
classGen.addMethod(laMethodeARajouter.getMethod());

// on liste les méthodes après en avoir ajouté une
methods = classGen.getJavaClass().getMethods();
System.out.println("\n*** Liste des méthodes après ajout ***\n");
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
} else
throw new RuntimeException("Class file is null!");
}
}




Pour en savoir plus : BCEL