Внедрить функцию в файл Java .class с помощью Haskell

Я написал синтаксический анализатор байт-кода Java с использованием Haskell, и он отлично работает. Однако следующий шаг поставил меня в тупик.

Моя программа на Haskell должна изменить файл .class, чтобы при выполнении программа на Java печатала:

«Введите здесь [имя метода]» перед выполнением метода и

«Выход из [имя метода здесь]» после выполнения метода.

Все, что я знаю, это то, что нам нужно будет добавить постоянный пул и таблицу методов с вызовами System.out.println, но я чувствую, что все еще что-то упускаю.

  • Как лучше всего подойти к этой проблеме?
  • Откуда вы знаете, как вызывать System.out.println в байт-коде?
  • Как сохранить строку с именем метода, чтобы потом вызывать ее как аргумент System.out.println?

person SamTheSammich    schedule 20.04.2012    source источник
comment
VMSpec — ваш друг . :)   -  person biziclop    schedule 21.04.2012
comment
внедрение новой функциональности в байт-код??? Я на самом деле рад, что у тебя проблемы с этим, звучит пугающе   -  person ControlAltDel    schedule 21.04.2012
comment
Я не уверен, что вам нужно выходить за пределы Java для решения этой проблемы - я подозреваю, что сработает какой-то метод проксирования. (Тем не менее, я уважаю вас за попытку сделать это таким образом. ;))   -  person Louis Wasserman    schedule 21.04.2012
comment
@LouisWasserman Это помечено как домашнее задание, поэтому я не думаю, что ОП делает это для развлечения :)   -  person biziclop    schedule 21.04.2012
comment
Возможно, вы ищете code.google.com/p/javaparser или publib.boulder.ibm. com/infocenter/rsmhelp/v7r0m0/topic/ ?   -  person kay    schedule 21.04.2012
comment
@ user1291492 что тебя пугает? Думали ли вы, что файл класса невосприимчив к попыткам перезаписи? Верно и обратное: очень легко разобрать и собрать файл класса.   -  person kay    schedule 21.04.2012
comment
@user1291492 user1291492 На самом деле в Java есть встроенные механизмы для этого. Google javaagent. Приложения включают профилирование, АОП и другие.   -  person yshavit    schedule 21.04.2012
comment
Тем не менее, если они получат такое задание, у них будет адский курс. Что за университет, ОП?   -  person Marko Topolnik    schedule 21.04.2012
comment
@MarkoTopolnik Техасский университет A&M   -  person SamTheSammich    schedule 21.04.2012


Ответы (4)


Что ж, это то, что вам дают различные библиотеки разработки байт-кода. ASM, BCEL и т. д. Специфика вашей домашней работы — это аспект, и AspectJ именно этим и занимается.

Похоже, домашнее задание — написать упражнение по разработке байт-кода на Haskell, поэтому вам нужно будет самостоятельно модифицировать файл класса. Предложение @biziclop выше верно. Сделайте до и после в файле класса, обратите внимание на дельту и сделайте то же самое самостоятельно из Haskell.

[ps: конечно, приведенный выше «кратчайший путь»: P - это если вам не хочется читать спецификацию JVM (как указано в комментарии к вашему q) и выяснять, как это сделать, как если бы вы писали Компилятор Java. Вы в основном вызываете метод, используя один из различных байтовых кодов для вызова - здесь вызов метода интерфейса - перед которым вам нужно иметь приемник, например. статическое поле вне класса System и имя метода в стеке. Подробности в спецификации.]

person alphazero    schedule 20.04.2012

Вероятно, самый простой подход — написать класс Java, содержащий единственный метод с кодом System.out.println(), скомпилировать его с кодом javac и наблюдать за результатами.

Как только вы освоитесь с ним, действуйте шаг за шагом.

  1. Добавьте вызов System.out.println() где-нибудь в java-файле, который вы хотите инструментировать. Это заботится о постоянном пуле. Напишите код на Haskell, который находит соответствующие константы и внедряет байт-код.
  2. Удалите вызов «костыль» из java-файла и реализуйте манипулирование постоянным пулом в Haskell.
person biziclop    schedule 20.04.2012

Просто возьмите свой листинг байт-кода Java и откройте простой скомпилированный класс с вызовом функции только System.out.println() и взгляните. Сделайте это для любых методов, которые вам нужны. Лучший способ выяснить это — провести небольшое исследование с помощью нескольких простых файлов кода и выполнить обратный инжиниринг по ходу дела. Вам нужно будет перевести нужное сообщение в юникод и передать его в свою функцию. Не забывайте и об этой части. Существуют различные программы, которые помогут вам в вашем стремлении покорить байт-код.

person Community    schedule 20.04.2012

Я думаю, что лучший способ решить эту проблему — использовать библиотеку Javassist (Помощник по программированию на Java). В классе Javassist.bytecode есть несколько полезных функций.

person tr4nc3    schedule 13.05.2012