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:
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
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); } }
Pour cela je crée un agent:
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 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
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*/ }
Je crée un fichier MANIFEST.MF:
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"); } }
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
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
Le résultat que j'obtiens actuellement:
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
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
Partager