2015-10-23 1 views
19

Je souhaite ajouter une arrayList dans une méthode pendant l'instrumentation. Je l'ai essayé comme mentionné dans (Javassist CannotCompileException when trying to add a line to create a Map) mais il jette une exception différente avec un java.lang.VerifyError.Comment créer une ArrayList en utilisant Javassist

public void createInsertBefore(String scenarioName, String className, CtMethod method, 
            String insertBefore) throws CannotCompileException { 
     method.addLocalVariable("startTime", CtClass.longType); 
     StringBuilder bBuilder = new StringBuilder(); 
     bBuilder.append("startTime = System.nanoTime();"); 
     bBuilder.append("System.out.println(startTime);"); 

     if((insertBefore!=null) && !insertBefore.isEmpty()){ 
      bBuilder.append(insertBefore); 
     } 

     bBuilder.append("java.util.List metadata = new java.util.ArrayList();"); 

     System.out.println(bBuilder.toString()); 
     method.insertBefore(bBuilder.toString()); 
} 

sortie reçu de l'instruction d'impression est,

startTime = System.nanoTime(); 
System.out.println(startTime); 
java.util.List metadata = new java.util.ArrayList(); 

Mais il jette exception suivante,

Exception in thread "main" java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:382) 
    at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:397) 
Caused by: java.lang.VerifyError 
    at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method) 
    at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144) 
    at org.wso2.das.javaagent.instrumentation.Agent.premain(Agent.java:57) 
    ... 6 more 
FATAL ERROR in native method: processing of -javaagent failed 
Aborted (core dumped) 

La situation est la même que précédemment, mais pourquoi faut-il lancer une autre exception . Qu'est-ce que je fais mal .... un peu d'aide s'il vous plaît ...

Update 1

lignes ajoutées avec (je l'ai enlevé quelques lignes d'impression), insertBefore,

startTime = System.nanoTime(); 
java.util.List metadata = new java.util.ArrayList(); 

insertAt

System.out.println("prepareStatement is running"); 
java.util.Map/*<String,String>*/ arbitraryMap = new java.util.HashMap/*String,String>*/(); 
arbitraryMap.put("query",$1);System.out.println(arbitraryMap); 

insertAfter

System.out.println(System.nanoTime()-startTime); 
+0

Cela ressemble à une erreur dans le code natif. – Thomas

+0

Que voulez-vous dire? U signifie le reste du code? Je pensais que le problème venait de cette affirmation, car si je commente cette ligne, l'instrumentation fonctionne bien. Par conséquent, je pense que c'est quelque chose qui ne va pas avec cette déclaration. – udani

+0

Votre code peut être erroné mais l'erreur se produit ici: 'sun.instrument.InstrumentationImpl.retransformClasses0 (Méthode native)' c'est-à-dire dans le code natif. Le JavaDoc sur l'erreur que vous obtenez dit: 'Jetez lorsque le" vérificateur "détecte qu'un fichier de classe, bien formé, contient une sorte d'incohérence interne ou un problème de sécurité. - Cela peut dépendre de la classe qui est améliorée, peut-être vous essayez d'insérer deux fois ou il y a déjà une variable appelée 'startTime',' metadata' etc. – Thomas

Répondre

6

Un VerifyError se produit lorsque les avis VM, qu'un déjà compilé bytecode est pas valide. Par exemple, lorsque vous essayez de lire une variable longue en utilisant une instruction de chargement pour un nombre entier ou des choses similaires. Donc, dans votre cas, le code compile, javaassist fait sa magie, mais la VM n'accepte pas le code. Ce doit être soit un bug en javassist ou un bug dans son utilisation.

Résolution du problème:

1) Pour autant que je sache, vous ne pouvez ajouter une instruction (pas une ligne) au début d'une méthode utilisant insertBefore. Si vous voulez en ajouter plus d'un, enveloppez-les dans des accolades {}, quelque chose comme method.insertBefore("{" + bBuilder.toString() + "}");

2) Vous n'avez pas ajouté les métadonnées comme une variable comme vous avez fait avec startTime

X) Si cela ou d'une autre erreur persiste, essayez d'écrire le fichier de classe dans un fichier sur le disque (en utilisant toClassFile vous pouvez accéder au fichier de classe modifié en tant que byte[]). Ensuite, vous pouvez utiliser des outils comme javap pour regarder le code compilé, et voir plus clairement ce qui se passe.