Timer ses méthodes

seareal Messages postés 24 Date d'inscription mardi 20 juillet 2004 Statut Membre Dernière intervention 8 juin 2011 - 20 juil. 2007 à 17:39
seareal Messages postés 24 Date d'inscription mardi 20 juillet 2004 Statut Membre Dernière intervention 8 juin 2011 - 23 juil. 2007 à 14:43
Bonsoir, je recherche un moyen de timer toutes les méthodes d'un programme sans pour autant les modifier à la main une à une.

J'ai essayé en utilisant BCEL (en adaptant un peu un code chinois), cela fonctionne bien sauf sur les méthodes contenant des "try - catch".
Si vous connaissez un moyen pour régler ce problème (ou un autre système), je vous en serais éterneeeeeeellement reconnaissant

Voilà le code de l'agent que j'utilise actuellement. Fonctionne bien sauf si une classe possède un code du genre
try
{
   // instruction non vide
}
catch (Exception e) {}

--------------------------------------------------------------------

import

java.io.ByteArrayInputStream;
import

java.io.ByteArrayOutputStream;
import

java.io.InputStream;
import

java.lang.instrument.ClassFileTransformer;
import

java.lang.instrument.IllegalClassFormatException;
import

java.lang.instrument.Instrumentation;
import

java.security.ProtectionDomain;

import

org.apache.bcel.Constants;
import

org.apache.bcel.classfile.ClassParser;
import

org.apache.bcel.classfile.JavaClass;
import

org.apache.bcel.classfile.Method;
import

org.apache.bcel.generic.ClassGen;
import

org.apache.bcel.generic.ConstantPoolGen;
import

org.apache.bcel.generic.InstructionConstants;
import

org.apache.bcel.generic.InstructionFactory;
import

org.apache.bcel.generic.InstructionList;
import

org.apache.bcel.generic.MethodGen;
import

org.apache.bcel.generic.ObjectType;
import

org.apache.bcel.generic.PUSH;
import

org.apache.bcel.generic.Type;

 

/**

*
Class
réécrivant

*/public

class Timer
implements ClassFileTransformer {

private
static
final String
EXT_NAME =
"_copie";

public
byte[] transform(ClassLoader loader, String className, Class cBR, ProtectionDomain pD,

byte[] classfileBuffer)

throws IllegalClassFormatException {

try{

// Charge la classe couranteString classFileName = className +

".class";InputStream is = Timer.

class .getClassLoader().getResourceAsStream(classFileName);JavaClass jclass =

new ClassParser(is, classFileName).parse();

// Initialise le ClassGenClassGen cgen =

new ClassGen(jclass);

// Ajoute le timer pour chaque méthode de la classeMethod[] methods = jclass.getMethods();

for (
int index = 0; index < methods.
length; index++) {

try {

// Pas de timer sur constructeur (... pour le moment !)

if (!methods[index].getName().equals(
" "))addTimer (cgen, methods[index]);

}

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

// Renvoie le code la classe ByteArrayOutputStream bos =

new ByteArrayOutputStream();cgen.getJavaClass().dump(bos);

return bos.toByteArray();

}

catch (Exception e) {

e.printStackTrace();

}

return
null;}

private
static
void addTimer(ClassGen cgen, Method method) {

// ----------------- DES INITIALISATIONS...
InstructionFactory ifact new InstructionFactory(cgen);InstructionList ilist

new InstructionList();ConstantPoolGen pgen = cgen.getConstantPool();

String cname = cgen.getClassName();

MethodGen wrapgen =

new MethodGen(method, cname, pgen);wrapgen.setInstructionList(ilist);

// ----------------- RENOMME LA METHODE ORIGINALE

// Méthode à modifierMethodGen methgen =

new MethodGen(method, cname, pgen);

// Suppression de la méthodecgen.removeMethod(method);

String iname = methgen.getName() +

EXT_NAME ;methgen.setName(iname);

// Ajout de la méhode, renomméecgen.addMethod(methgen.getMethod());

// ----------------- PREPARE LA NOUVELLE METHODE

// Type de retour de la méthodeType result = methgen.getReturnType();

// Paramètres de la méthodeType[] parameters = methgen.getArgumentTypes();

int stackIndex = methgen.isStatic() ? 0 : 1;

for (
int i = 0; i < parameters.
length; i++)stackIndex += parameters[i].getSize();

// Enregistre le temps au début de la méthodeilist.append(ifact.createInvoke(

"java.lang.System",
"currentTimeMillis", Type.
LONG , Type.
NO_ARGS, Constants.
INVOKESTATIC));ilist.append(InstructionFactory.createStore(Type.

LONG, stackIndex));

// Méthode static ou non TODO Voir pour constructeurs ici

int offset = 0;

short invoke = Constants.
INVOKESTATIC ;

if (!methgen.isStatic()) {

ilist.append(InstructionFactory.createLoad(Type.

OBJECT, 0));offset = 1;

invoke = Constants.

INVOKEVIRTUAL ;}

// Les paramètres

for (
int i = 0; i < parameters.
length; i++) {

Type type = parameters[i];

ilist.append(InstructionFactory. createLoad (type, offset));

offset + = type.getSize();

}

// Signature de la méthodeilist.append(ifact.createInvoke(cname, iname, result, parameters, invoke));

// ???

if (result ! = Type.
VOID )ilist.append(InstructionFactory.createStore(result, stackIndex+2));

// ----------------- AFFICHAGE DU TEMPS ECOULE

ilist.append(ifact.createFieldAccess(

"java.lang.System",

"out",
new ObjectType(
"java.io.PrintStream"),Constants.

GETSTATIC));ilist.append(InstructionConstants.

DUP);ilist.append(InstructionConstants.

DUP);String text = cgen.getClassName() +

"\t"+ methgen.getName() +
"\t";ilist.append(

new PUSH(pgen, text));

ilist.append(ifact.createInvoke(

"java.io.PrintStream",

"print", Type.
VOID,
new Type[] { Type.
STRING },Constants.

INVOKEVIRTUAL));ilist.append(ifact.createInvoke(

"java.lang.System",

"currentTimeMillis", Type.
LONG, Type.
NO_ARGS, Constants.

INVOKESTATIC));ilist.append(InstructionFactory.

createLoad(Type.

LONG, stackIndex));ilist.append(InstructionConstants.

LSUB);

ilist.append(ifact.createInvoke(

"java.io.PrintStream",

"print", Type.
VOID,
new Type[] { Type.
LONG },Constants.

INVOKEVIRTUAL));ilist.append(

new PUSH(pgen,
" ms."));ilist.append(ifact.createInvoke(

"java.io.PrintStream",

"println", Type.
VOID,
new Type[] { Type.
STRING },Constants.

INVOKEVIRTUAL));

// ----------------- RENVOI LE RETOUR DE LA METHODE ORIGINALE

if (result ! = Type.
VOID) ilist.append(InstructionFactory.createLoad(result, stackIndex+2));

ilist.append(InstructionFactory.createReturn(result));

// ----------------- POUR FINIR...wrapgen.stripAttributes(

true);wrapgen.setMaxStack();

wrapgen.setMaxLocals();

cgen.addMethod(wrapgen.getMethod());

ilist.dispose();

}

/**

*
Correspond
au
"Main"
de
l'agent.
Utiliser
l'appel
:

*
java
-javaagent:test.jar
package.MainClass

*
@param
options

*
@param
ins

*/

public
static
void premain(String options, Instrumentation ins) {

ins.addTransformer(

new Timer());}

}

2 réponses

cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
20 juil. 2007 à 20:16
Utilise un outil de profilling, ils sont fait pour mesurer le temps passé dans les méthodes pour savoir où est-ce qu'il faut optimiser.

Perso j'utilise JProfiler
0
seareal Messages postés 24 Date d'inscription mardi 20 juillet 2004 Statut Membre Dernière intervention 8 juin 2011
23 juil. 2007 à 14:43
Merci pour ta réponse, je connaissais déjà JProfiler.
J'aurais été content de pouvoir faire marcher cela m'enfin tant pis.
0
Rejoignez-nous