Элегантный способ изменить тип (класса-) экземпляра в байт-коде Java
В течение некоторого времени я работал над решением следующей проблемы. Допустим, у меня есть следующий код Java:
public class A {
public void start() {
List l = new ArrayList();
l.add("abc");
System.out.println( l.get(0) );
}
}
Результатом компиляции этого кода является файл класса A.class
, содержащий байт-код Java. Я написал ClassLoader
, который загружает A.class
и выполняет start()
, Мое намерение заменить в загруженном A.class
(байт-код) new ArrayList()
с MyArrayList()
:
//Before
List l = new ArrayList();
//After
List l = new MyArrayList();
Класс MyArrayList
определяется аналогично: class MyArrayList extends ArrayList
1 ответ
Вы можете использовать такой инструмент, как ASM, чтобы проанализировать файл и заменить возникновение любого ArrayList
с MyArrayList
, Это, однако, потребует, чтобы MyArrayList
определяет конструкторы с идентичной сигнатурой для конструкторов, определенных в ArraysList
,
Следующий вопрос - когда вы определяете изменения. У вас есть следующие возможности:
- Измените реализацию во время сборки: вы можете написать плагин для инструмента сборки, который будет применять ваши преобразования.
- Измените реализацию во время выполнения, используя агент Java: API Attach позволяет вам изменять загруженный класс даже во время выполнения.
- Измените реализацию до первой загрузки класса: вы можете использовать загрузчик пользовательских классов для загрузки вашего измененного класса. Это должно произойти до того, как класс будет загружен регулярно!