Bonjour,
Vous pouvez faire le test chez vous sans problème il suffit de récupérer la dernière version de ASM Java bytecode manipulation and analysis framework.

Je veux instrumenter mon code source.

J'y arrive très bien seulement quelques classes ne sont pas instrumentées car elles sont chargées trop tot (avant même que l'instrumenteur se met en place). Donc si elles sont déjà chargées par le ClassLoader c'est trop tard, je peux plu les instrumenter (car l'instrumentation se fait lors du chargement de la classe par le ClassLoader).

Heureusement il existe une méthode : Instrumentation.retransformClasses(Class<?> ) que malheureusement je n'arrive pas utiliser.

Comme vous pouvez le constater dans la doc :
http://java.sun.com/javase/6/docs/ap...lang.Class...)
Cette méthode est très capricieuse (à la moindre exception relevée, aucune classe de l'ensemble des classes passées en paramètre à la méthode retransform n'est transformé)

Bon je vous explique ce que je veux faire:
Voila la classe que je veux instrumenter dynamiquement:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
 
public class ClassTest{
    public static void main(String[] arg){
        String s = new String("0123456789");
         int i = s.indexOf("4");
         System.out.println(i);
    }
}
Donc en gros, le résultat de l'instrumentation serait :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 
Je suis dans : ClassTest.main([Ljava.lang.String)V
Je suis dans : java.lang.String <init>(Ljava.lang.String)V
Je suis dans : java.lang.String.indexOf(I)I
je suis dans : java.io.PrintStream(I)V
Pour cela je crée un agent:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
public class SimpleTransformer2 implements ClassFileTransformer {
     Instrumentation instrum;
 
     public static void premain(String agentArguments, Instrumentation instrumentation) {    
        instrumentation.addTransformer(new SimpleTransformer2(instrumentation),true);    
    }    
 
    public SimpleTransformer2(Instrumentation i) {
        super();
        instrum = i;
        try{
 
            java.util.Vector<Class> v = new java.util.Vector<Class>();
            Class[] cl = instrum.getAllLoadedClasses();
 
            int nb = 0;
            for(int a=0;a<cl.length;a++){
                if(instrum.isModifiableClass(cl[a])){
                    v.add(cl[a]);
 
                }
            }
            Class[] cl2 = new Class[v.size()];
            v.toArray(cl2);
            instrum.retransformClasses(cl2);
 
        }catch(Exception e){
                e.printStackTrace();
        }
 
    }
 
    public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException {
 
                //cette instruction me permet de connaitre le nom des classes qui sont passées par la méthode transform
        System.out.println("--->Transform: " + className);
 
        byte[] result = bytes;
        try {
                //CODE ASM
                ClassReader reader = new ClassReader(bytes);
				ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS);
				MyClassAdapter mca = new MyClassAdapter(writer, className);
				reader.accept(mca , ClassReader.SKIP_DEBUG);
				result = writer.toByteArray();		             
        }
        catch(Exception e) {
            e.printStackTrace();
        }
        return result;
    }
 
/** Après il y a mon code en ASM qui instrumente les différentes méthodes en indiquant le nom des méthodes qui sont appelées*/
}
Pour ceux qui voudrai tester voila le code qu'il faut insérer à la place du dernier commentaire:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/********************************ClassAdapter**************************************/	
 
    private class MyClassAdapter extends ClassAdapter {
 
		private String className;
 
		MyClassAdapter(ClassVisitor cv, String theClass) {
		    super(cv);
		    className = theClass;
 
		}
 
		@Override public void visit(int arg0, int access, String name, String signature,String superName, String[] interfaces) {
			System.out.println(className);
			cv.visit(arg0, access, name, signature, superName, interfaces);	
		}
 
		@Override public MethodVisitor visitMethod(int arg0, String name, String descriptor, String signature, String[] exceptions) {
		    MethodVisitor mv = cv.visitMethod(arg0, name, descriptor, signature, exceptions);
		/*	mv = new TraceMethodVisitor(mv){
				    @Override public void visitEnd(){
				    		mv.visitCode();
				    		print(new PrintWriter(System.out));
				    }
			    };
		*/	    
		    return new MyMethodAdapter(mv,className,name,descriptor);
		}
    }
 
/********************************MethodAdapter**************************************/	
 
    private class MyMethodAdapter extends MethodAdapter {
	private String methodName;
	private String methodDescriptor;
	private String className;
 
		MyMethodAdapter(MethodVisitor mv, String theClass, String name, String descriptor) {
		    super(mv);
		    methodName = name;
		    methodDescriptor = descriptor;
		    className = theClass;
		}
 
		@Override public void visitCode() {
			mv.visitCode();
			//Every method print her name at the beginning
			mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
			mv.visitLdcInsn("Je suis dans " + className + "." + methodName + "(" + methodDescriptor + ") called");
			mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
 
		}
 
	}
Je crée un fichier MANIFEST.MF:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
 
Manifest-Version: 1.0 
Premain-Class: SimpleTransformer2
Can-Retransform-Classes: true
Can-Redefine-Classes: true
Boot-Class-Path: asm-3.2.jar asm-analysis-3.2.jar asm-commons-3.2.jar asm-tree-3.2.jar asm-util-3.2.jar asm-xml-3.2.jar
voila la suite de commande que je tape (sous windows):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 
set CLASSPATH=%CLASSPATH%;[...]\asm-3.2\lib\asm-3.2.jar;[...]\asm-3.2\lib\asm-util-3.2.jar
javac *.java
jar -cfm test.jar MANIFEST.MF *
java -javaagent:test.jar ClassTest
Le résultat que j'obtiens actuellement:
Je suis dans ClassTest.main

Il n'a pas détecter le String<init> et le String.indexOf parce que la classe String n'a pas été instrumentée.

Est ce que quelqu'un a une idée? Merci pour vos réponses