2010-11-16 30 views
4

En utilisant une bibliothèque comme ASM ou cglib, existe-t-il un moyen d'ajouter des instructions bytecode à une classe pour exécuter du code chaque fois que la valeur d'un champ de classe est définie?Manipulation de bytecode pour intercepter la valeur d'un champ

Par exemple, disons que j'ai cette classe:


    public class Person 
    { 
     bool dirty; 
     public String name; 
     public Date birthDate; 
     public double salary; 
    } 

Disons une section de code contient cette ligne:

person.name = "Joe";

Je veux que cette instruction à intercepter si le dirty Le drapeau est défini sur true. Je sais que cela est possible pour les méthodes setter - person.setName (“Joe”) - comme les méthodes de classe peuvent être modifiées par manipulation de bytecode, mais je veux faire la même chose pour un champ. Est-ce possible, et si oui, comment?

EDIT

Je veux éviter de modifier la section de code qui accède à la classe, je suis à la recherche d'un moyen de garder le code d'interception dans le cadre de la classe Person. Existe-t-il des pseudo-méthodes d'accès aux champs, similaires aux propriétés des classes Python?

+0

post EDIT. Vous pouvez vérifier spécifiquement si la classe en cours de chargement est Person, et si c'est le cas, choisissez d'appliquer cette instrumentation particulière. Cela ne répond-il pas à vos exigences? –

+0

Merci, ce que j'essaie de trouver est la suivante: Où puis-je mettre le bytecode? Y at-il une méthode qui est appelée sur la classe chaque fois qu'un de ses champs est accédé? Ou devrais-je parcourir toutes les autres classes, trouver des instances d'accès aux champs et les remplacer par des appels de méthodes? –

+1

pensé que je le mentionnerais, mais quand un champ est privé, mais que cette classe est une classe interne d'une autre classe, cette classe externe peut toujours accéder au champ directement même si elle est privée. Il le fait en générant une méthode synthétique pour accéder au champ. Si vous êtes limité à ce cas, vous pouvez simplement modifier la méthode de synthèse et cela fonctionne comme python. (mais en général, la réponse est non, vous devez modifier les méthodes normales.) – MeBigFatGuy

Répondre

0

En bref, vous avez besoin d'injecter bytecode qui fait ce qui suit dans la méthode d'intérêt:

if (person.name.equals("Joe") { 
    dirty = true; 
} 

Vous ne pouvez pas évaluer le terrain au moment de l'instrumentation - il doit être à l'exécution lorsque la méthode est en cours d'exécution.

En ce qui concerne votre question de savoir comment, effectuez les opérations suivantes:

  • Recopiez le code dans une classe de test et générer une version ascii du bytecode pour voir ce qui a été généré. Vous pouvez le faire facilement avec javap.
+0

Vous pouvez modifier la classe source comme vous le souhaitez, puis utiliser asmify pour générer le code asm pour produire cette transformation. – MeBigFatGuy