Удаление инструкций из байт-кода Java - PullRequest
11 голосов
/ 10 февраля 2012

Я использовал Javassist для динамического управления классами по мере их загрузки. Хотя добавить код в метод с помощью Javassist относительно просто, я не смог найти способ удалить код.

В настоящее время я моделирую удаление кода с помощью инструкций nop для замены целевых кодов операций и любых параметров. Тем не менее, я считаю, что это в основном взломать:

  • Каждый код операции должен обрабатываться отдельно, поскольку длина байтов параметров отличается. В некоторых случаях мне также нужно выбирать между nop и pop , в зависимости от того, влияет ли удаленный код операции на стек или нет. Этот вид манипулирования начинает становиться утомительным - и код, который это делает, становится соответственно запутанным. Поэтому, естественно, я надеюсь на существующее решение.

  • Окончательный результат заполняется инструкциями nop . Хотя JVM должна оптимизировать их без ущерба для производительности, результирующий байт-код все еще довольно не элегантен и больше, чем должен быть. Это в большей степени вопрос эстетики, но об этом еще нужно подумать.

К сожалению, простого смещения частей массива байт-кода для закрытия пробела недостаточно - любые ссылки на перемещенный код (например, индексы инструкций ветвления) также должны быть обновлены.

Можно ли удалить инструкции с помощью Javassist? В качестве альтернативы, есть ли библиотека манипулирования байт-кодом, которая позволила бы мне сделать это легко, без необходимости самому анализировать байт-код?

Ответы [ 2 ]

3 голосов
/ 10 февраля 2012

Apache BCEL позволяет удалять инструкции :

Удаление инструкций также очень просто;все описатели команд и содержащиеся в них инструкции удаляются из списка команд и удаляются.Однако метод delete () может выдать исключение TargetLostException, если есть нацеливающие инструкции, все еще ссылающиеся на одну из удаленных инструкций.Пользователь вынужден обрабатывать такие исключения в предложении try-catch и перенаправлять эти ссылки в другом месте.

Пример также можно найти в руководстве.

0 голосов
/ 13 февраля 2012

Из учебника по javassist:

Javassist не позволяет удалить метод или поле, но позволяет изменить имя. Поэтому, если метод больше не нужен, его следует переименовать и изменить на частный, вызвав setName () и setModifiers (), объявленные в CtMethod.

...