Обработка байт-кода для перехвата установки значения поля

Есть ли способ добавить инструкции байт-кода в класс, используя библиотеку, такую ​​​​как ASM или cglib, для выполнения кода всякий раз, когда установлено значение поля класса?

Например, предположим, что у меня есть этот класс:


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

Допустим, часть кода содержит эту строку:

person.name = "Joe";

Я хочу, чтобы эта инструкция была перехвачена, поэтому для флага dirty установлено значение true. Я знаю, что это возможно для методов установки -- person.setName (“Joe”) -- поскольку методы класса могут быть изменены с помощью манипуляций с байт-кодом, но я хочу сделать то же самое для поля.

Возможно ли это, и если да, то как?

ИЗМЕНИТЬ

Я хочу избежать изменения раздела кода, который обращается к классу, я ищу способ сохранить код перехвата как часть класса Person. Существуют ли псевдометоды для доступа к полям, подобные свойствам в классах Python?


person Tony the Pony    schedule 16.11.2010    source источник
comment
пост РЕДАКТИРОВАТЬ. Вы можете специально проверить, является ли загружаемый класс Person, и если это так, выбрать применение к нему этого конкретного инструментария. Это не соответствует вашим требованиям?   -  person Amir Afghani    schedule 16.11.2010
comment
Спасибо, я пытаюсь выяснить следующее: куда мне поместить байт-код? Есть ли метод, который вызывается в классе при доступе к одному из его полей? Или мне придется рыться во всех других классах, находить экземпляры доступа к полям и заменять их вызовами методов?   -  person Tony the Pony    schedule 17.11.2010
comment
думал, что упомяну об этом, но когда поле является частным, но этот класс является внутренним классом другого класса, этот внешний класс все еще может получить доступ к полю напрямую, даже если оно является частным. Это достигается путем создания синтетического метода доступа к полю. Если вы ограничены этим случаем, вы можете просто изменить синтетический метод, и тогда он будет работать так же, как python. (но в целом ответ отрицательный, вы должны изменить обычные методы.)   -  person MeBigFatGuy    schedule 10.06.2011


Ответы (2)


Существует два байт-кода для обновления полей: putfield и putstatic (см. http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc11.html). Они будут найдены в коде используемого класса, поэтому нет возможности просто изменить Person.

person Anon    schedule 17.11.2010

Короче говоря, вам нужно ввести байт-код, который делает следующее в интересующем вас методе:

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

Вы не можете оценить поле во время инструментирования — оно должно быть во время выполнения, когда метод выполняется.

Что касается вашего вопроса о том, как, попробуйте следующее:

  • Напишите код в тестовом классе и сгенерируйте ASCII-версию байт-кода, чтобы увидеть, что было сгенерировано. Вы можете легко сделать это с помощью javap.
person Amir Afghani    schedule 16.11.2010
comment
вы можете изменить исходный класс так, как вам нужно, а затем использовать asmify для генерации ассемблерного кода для выполнения этого преобразования. - person MeBigFatGuy; 10.06.2011