Удаление инструкций из байт-кода Java
Я использую Javassist для динамического управления классами по мере их загрузки. Хотя добавление кода в метод относительно легко с помощью Javassist, я не смог найти способ удалить код.
в это время я имитирую удаление кода с помощью НОП инструкции по замене целевых кодов операций и любых параметров. Тем не менее, я считаю, что это в основном Хак:
каждый код операции должен обрабатываться отдельно, так как длина байта параметров отличается. В некоторых случаях мне также нужно выбрать между НОП и поп, в зависимости от того, влияет ли удаленный код операции на стек или нет. Такого рода манипуляции начинают становиться утомительными - и код, который это делает, становится соответственно запутанным. Поэтому, естественно, я надеюсь на существующее решение.
конечный результат заполняется НОП инструкции. Хотя JVM должен оптимизировать их без влияния на производительность, результирующий байт-код все еще довольно неэлегантен и больше, чем должен быть. Это больше вопрос эстетики, но это все еще что-то, чтобы рассмотреть.
к сожалению, просто сдвигать части массива байт-кода, чтобы закрыть пробел, недостаточно - любые ссылки на перемещенный код (например, индексы инструкций ветви) также должны быть обновлены.
можно ли удалить инструкции с помощью Javassist? Кроме того, есть ли библиотека манипуляций байт-кодом, которая позволила бы мне сделать это легко, без необходимости по существу анализировать байт-код самостоятельно?
2 ответов
Апач как bcel позволяет удалить инструкции:
удаление инструкций также очень просто; все дескрипторы инструкций и содержащиеся в них инструкции в заданном диапазоне удаляются из списка инструкций и удаляются. Однако метод delete () может вызывать исключение TargetLostException, когда есть целеуказатели инструкций, все еще ссылающиеся на одну из удаленных инструкций. Пользователь вынужден обрабатывать такие исключения в предложение try-catch и перенаправить эти ссылки в другое место.
вы также можете найти пример в руководстве.
из учебника javassist :
Javassist не позволяет удалить метод или поле, но позволяет изменить имя. Поэтому, если метод больше не нужен, его следует переименовать и изменить как частный метод, вызвав setName() и setModifiers (), объявленные в CtMethod.