Как сгенерировать байт-код и сохранить в файл .class? - PullRequest
8 голосов
/ 14 октября 2011

У меня есть следующее странное требование.

Мне дано:

  1. Список имен некоторых методов.
  2. Имена и типы параметров вышеМетоды.
  3. Функциональность вышеуказанных методов.Это выглядит следующим образом: Для каждого параметра метод преобразует его в строку, используя toString, и получает массив строк.К этому массиву метод применяет функцию foo.Функция foo принимает в качестве входа тип String [] и выводит String.Методы возвращают то, что возвращает foo.Код foo предоставляется внутри объекта Java и должен быть доступен как черный ящик.

Информация в 1. и 2. может быть в текстовом или XML-файле.Для этой цели мы можем считать его доступным внутри объекта Java любым способом, который мы выберем.

Задача - создать файл .class (т. Е. Байт-код), который реализует эти методы и может быть запущен на JVM.

Я думаю, эта библиотека на ассемблере будет одним из способов сделать это.Кто-нибудь может предложить более простой способ?

[EDIT:] Я могу придумать еще один способ: сначала сгенерировать файл .java, а затем скомпилировать его, чтобы получить файл .class.

[Контекст:] Я должен сделать это для нескольких сотен методов.Я хочу ярлык, чтобы я мог автоматизировать свою работу, а не писать код вручную.

Ответы [ 3 ]

9 голосов
/ 14 октября 2011

Вы можете сгенерировать необходимый программный код в синтаксисе Java и превратить его в файл класса с помощью компилятора.Можно создать экземпляр javac во время выполнения и передать ему байтовый массив вместо расположения исходного файла.Вероятно, это проще всего поддерживать другим программистам.

Если вы хотите генерировать байт-код напрямую, asm - это библиотека, которая наиболее часто используется.

6 голосов
/ 14 октября 2011

Вот список библиотек байт-кода с открытым исходным кодом: http://java -source.net / open-source / bytecode-library

Посмотрите на Javassist .

1 голос
/ 14 октября 2011

Я видел, как вы ответили на мой комментарий, но мне до сих пор не ясно, почему вы хотите сгенерировать код для последующей упаковки в банку, просто введите его:)

Теперь, если вам нужен типизированный API-интерфейс с одинаковым поведением для всех методов, вы можете предоставить динамический прокси-сервер для данного интерфейса (в связи с этим возникает вопрос о том, как создать интерфейс:)

Вот пример, где все вызовы всех методов MyInterface будут обрабатываться методом invoke (просто добавьте методы в интерфейс для его проверки) ...

package test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test {

interface MyInterface {

    String methodOne(String s);

    String methodTwo(String s, Integer i);
}

static MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
        MyInterface.class.getClassLoader(),
        new Class[] { MyInterface.class }, new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {  
                StringBuilder result = new StringBuilder();
                for (Object arg : args) {
                    result.append(arg.toString());
                }
                return result.toString();
            }
        });

public static void main(String[] args) {
    System.out.println(proxy.methodOne("hello"));       
    System.out.println(proxy.methodTwo("world", 5));

}   

}
...