Как сгенерировать байт-код существующего класса во время выполнения в Java?

Как сгенерировать байт-код существующего класса во время выполнения в Java?

Мой существующий класс, скажем, Foo.java

public class Foo {

    public String saySomething() {
        return "Hello World";
    }
}

Теперь я хочу сгенерировать байт-код этого существующего класса Foo.java и, возможно, использовать его в другом экземпляре JVM. Пожалуйста, поймите, что я не создаю класс во время выполнения, так как у меня уже есть класс с именем Foo.java. Открыт для любых библиотек, таких как ASM или ByteBuddy и т. д.


person user1870400    schedule 18.10.2018    source источник
comment
Если класс уже существует, просто загрузить его? Если его нет в пути к классам, может помочь новый загрузчик классов. Или вам действительно нужны байты того класса (или байт-кода), тогда поясните для чего.   -  person CoronA    schedule 18.10.2018
comment
Мне действительно нужны байты этого класса. аналогично этому programiz.com/python-programming/methods/built-in /компилировать   -  person user1870400    schedule 18.10.2018
comment
Это противоречиво. В комментарии вы представляете функцию, которая преобразует байты в объект класса, а не класс в объект байта. может быть, это поможет, если вы объясните, для чего вам это нужно.   -  person CoronA    schedule 18.10.2018
comment
Где? Я всегда хотел, чтобы существующий класс байтировал объект во время выполнения.   -  person user1870400    schedule 18.10.2018
comment
да, я имел в виду, что мне нужен байт-код моего класса Foo.java выше во время выполнения   -  person user1870400    schedule 18.10.2018
comment
Функция compile из python работает ровно по-другому. Он преобразует байты в объект класса.   -  person CoronA    schedule 18.10.2018
comment
Вы можете обратиться к dzone. ком/статьи/   -  person Miller Cy Chan    schedule 18.10.2018
comment
@CoronA Это неверное утверждение. Функция компиляции в python берет исходный код и компилирует в байт-код во время выполнения. Я делал это так много раз.   -  person user1870400    schedule 18.10.2018
comment
Лучше обратитесь к stackoverflow.com/questions/21544446/   -  person Miller Cy Chan    schedule 18.10.2018
comment
@MillerCyChan Ты понял! Я именно это ищу. Интересно, почему это не является частью стандартного пакета Java, но в любом случае не могли бы вы сказать мне, будет ли эта строка JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); вызывать какой-то внешний двоичный файл вне JVM? или это просто библиотечная функция, которая берет источник и возвращает байт-код?   -  person user1870400    schedule 18.10.2018
comment
Требуется JDK, поэтому он будет вызывать javac вне JVM в соответствии с stackoverflow.com/questions/46096598/   -  person Miller Cy Chan    schedule 18.10.2018
comment
@MillerCyChan Большое спасибо. Есть ли способ сделать это без вызова внешнего двоичного файла, такого как javac? Мне просто нужно правильное представление IR байт-кода, которое не зависит от машины, поэтому действительно ли нужно вызывать javac?   -  person user1870400    schedule 18.10.2018
comment
По крайней мере, jre требуется, пожалуйста, найдите слова Сначала я снова использовал jre из stackoverflow.com/questions/46096598/   -  person Miller Cy Chan    schedule 18.10.2018


Ответы (2)


[Отредактировано после уточнения в комментариях]

следующая статья описывает, как скомпилировать класс из исходного кода во время выполнения, используя ToolProvider.getSystemJavaCompiler().

person Yoav Gur    schedule 18.10.2018
comment
Loads a given file (presumably .class) into a byte array Это предполагает, что у меня уже есть файл .class, но это не тот случай, когда у меня есть Foo.java, поэтому мне нужно иметь возможность компилировать во время выполнения и получать байт-код во время выполнения. В питоне это очень просто. - person user1870400; 18.10.2018
comment
См. getClass(String name) в той же статье, чтобы получить имя файла из полного имени класса. - person Yoav Gur; 18.10.2018
comment
мне нужно что-то вроде этого -в/компилировать - person user1870400; 18.10.2018
comment
Я отредактировал ответ, чтобы ответить на недостающие фрагменты, возникающие в связи с вашими вопросами. - person Yoav Gur; 18.10.2018
comment
Привет, я не уверен, что вы следуете моему вопросу. Я хочу перейти от существующего класса Foo.java к байт-коду во время выполнения, а не от байт-кода к классу. - person user1870400; 18.10.2018
comment
Что вы подразумеваете под во время выполнения? Если вы запускаете скомпилированную Java-программу, у вас уже есть .class, иначе как это «время выполнения»? В приведенном выше коде показано, как получить байт-код (в виде массива байтов, который можно преобразовать в строку) из класса во время выполнения. - person Yoav Gur; 18.10.2018
comment
Я хочу, чтобы компиляция происходила во время выполнения и в результате получала байт-код, чтобы я мог, скажем, распечатать байт-код на экране. - person user1870400; 18.10.2018
comment
Я понимаю. Тогда взгляните на это: dzone.com/articles/ - person Yoav Gur; 18.10.2018
comment
Ты понял! Я именно это ищу. Интересно, почему это не является частью стандартного пакета Java, но в любом случае, не могли бы вы сказать мне, если эта строка JavaCompilercompiler = ToolProvider.getSystemJavaCompiler(); будет вызывать какой-то внешний двоичный файл за пределами JVM? или это просто библиотечная функция, которая берет источник и возвращает байт-код? - person user1870400; 18.10.2018
comment
ToolProvider является частью rt.jar, который является частью JVM, но сам компилятор предоставляется платформой. См.: docs.oracle.com/ javase/8/docs/api/javax/инструменты/ - person Yoav Gur; 18.10.2018
comment
Читаю комментарии выше. Есть ли способ сделать это без вызова внешнего двоичного файла, такого как javac? Мне просто нужно правильное представление IR байт-кода, которое не зависит от машины, поэтому действительно ли нужно вызывать внешний двоичный файл, такой как javac? - person user1870400; 18.10.2018
comment
Байт-код не зависит от машины, но вам все равно нужен какой-то компилятор, чтобы получить его из исходного кода, не так ли? - person Yoav Gur; 18.10.2018
comment
да, но вопрос в том, должен ли в этом случае компилятор быть внешним двоичным файлом? может это просто библиотечная функция? - person user1870400; 18.10.2018
comment
Судя по декомпилированному коду (см. следующий комментарий), это похоже на библиотеку, но я не удивлюсь, если эта реализация доступна только с JDK, а не с JRE. - person Yoav Gur; 18.10.2018
comment
общедоступный статический JavaCompiler getSystemJavaCompiler() { return (JavaCompiler)instance().getSystemTool(JavaCompiler.class, com.sun.tools.javac.api.JavacTool); } - person Yoav Gur; 18.10.2018
comment
Не могли бы вы обновить свой ответ тогда? используя JavaCompiler getSystemJavaCompiler() и получая байт-код класса, такого как Foo.java выше - person user1870400; 18.10.2018

Для этого вам не нужна библиотека, любой файл класса — это просто ресурс, как и любой другой файл, который может быть найден Foo.class.getResource("Foo.class"). Вы можете открыть поток этого ресурса и прочитать его байт точно так же, как и любого другого ресурса.

Если вы уже используете Byte Buddy, вы можете получить байты с помощью: ClassFileLocator.ForClassLoader.read(Foo.class) но если это все, что вам нужно, использование библиотеки будет излишним.

person Rafael Winterhalter    schedule 24.10.2018