Можно ли сделать программу Java, которая выводит исходный код в новый файл и компилирует его, и запускает скомпилированную программу?
Программы, которые воспроизводят себя
Ответ 1
Да, это возможно. Тривиальная реализация будет заключаться в следующем: иметь исходный код в строке, сохранить строку в файле и заполнить ее собственную строку той же строкой (в противном случае начальная строка будет иметь бесконечный размер из-за рекурсивного способа этого реализация), скомпилировать файл и запустить скомпилированный файл (который, в свою очередь, сделает то же самое).
Нетривиальные реализации значительно сложнее.
Ответ 2
Обновление:
Хорошо, возможно, также сделать автозапуск. Наслаждайтесь безумием. Беги на свой страх и риск.
Да, это возможно, потому что я на самом деле написал это. Он не делает часть RUN (это слишком сумасшедшее, потому что, как говорили другие, это вызовет бесконечный цикл),, но вот оно: Quine.java
import java.io.*;
public class Quine {
public static void main(String[] args) throws Exception {
char q = 34;
String out = "Quine$";
String text = (
"import java.io.*; " +
"public class [OUT] { " +
"public static void main(String[] args) throws Exception { " +
"char q = 34; String out = `[OUT]$`; String text = `[TEXT]`; " +
"PrintWriter pw = new PrintWriter(out + `.java`); " +
"pw.format(text, 34, out, text); " +
"pw.close(); Runtime runtime = Runtime.getRuntime(); " +
"runtime.exec(`javac ` + out + `.java`).waitFor(); " +
"runtime.exec(`java ` + out); " +
"} " +
"}"
).replace("`", "%1$c").replace("[OUT]", "%2$s").replace("[TEXT]", "%3$s");
PrintWriter pw = new PrintWriter(out + ".java");
pw.format(text, 34, out, text);
pw.close();
Runtime runtime = Runtime.getRuntime();
runtime.exec("javac " + out + ".java").waitFor();
runtime.exec("java " + out);
}
}
Итак, как начать сумасшествие:
-
javac Quine.java
для компиляции -
java Quine
, чтобы запустить его- Он будет производить, компилировать и запускать
Quine$
- Он будет производить, компилировать и запускать
- Я убедился, что
Quine.java
максимально читаем, поэтому основное отличие отQuine$.java
- форматирование и 3xreplace
. Меньшая разница заключается в том, чтоQuine$.java
имеетout
установлен наQuine$$
. -
Quine$
будет производить, компилировать и запускатьQuine$$
-
Quine$$
будет производить, компилировать и запускатьQuine$$$
-
Quine$$$
будет производить, компилировать и запускатьQuine$$$$
- ...
Обратите внимание, что это не делает никакой обратной обработки или обманывает, читая исходный код .java
и т.д. Quine
является генератором quine, поскольку он создает другой код, отформатированный по-разному, но Quine$
в значительной степени настоящий автономный quine: он воспроизводит себя, он просто переносит его Quine$$
(который воспроизводит себя и переписывается на Quine$$$
и т.д.).
Таким образом, технически нет бесконечного цикла: в конечном итоге он остановится, когда файловая система не сможет обработать другой $
. Я смог вручную остановить безумие, решив удалить все Quine$*
файлы, но бежать на свой страх и риск!!!
Ответ 3
Конечно, это работает. Посмотрите rosetta code и перейдите к Quine, которая является самореференционной программой, которая может без каких-либо внешних доступ, вывод собственного источника.
Вот пример для quine в Java.
Ответ 4
Программы, которые воспроизводят себя или программы саморепликации, называются Quine Programs
Пример программы в Java, которая воспроизводит себя.
public class QuineProgram {
public static void main(String[] args){
String f = "public class QuineProgram { "
+ "public static void main(String[] args)"
+ "{ String f =%c%s%1$c;"
+ " System.out.printf(f,34,f);}} ";
System.out.printf(f, 34, f);
}
}
Вывод:
public class QuineProgram { public static void main(String[] args){ String f ="public class QuineProgram { public static void main(String[] args){ String f =%c%s%1$c; System.out.printf(f,34,f);}} "; System.out.printf(f,34,f);}}
Ответ 5
Для этого вы можете использовать Java Compiler API (JSR-199). Ниже приведен код из JSR-199, который компилирует код из String (слегка модифицированный, чтобы скомпилировать его). Код фактически компилирует исходный код из String
в массив байтов (т.е. Не записывает на диск), загружает его и затем выполняет его через отражение:
-
MemoryFileManager.java
: файловый менеджер для компиляции строк в байтовые массивы. -
ByteArrayClassLoader.java
: загрузчик классов, который загружает классы из массивов байтов. -
CompileFromString.java
: класс, который объединяет все вместе.
Это может быть отправной точкой (кредиты Питеру Ван дер Аэ, оригинальному автору).
Кстати, вам нужно, конечно, JDK использовать этот API.
Ответ 6
Я не знаю точно, что вы хотите, но я думаю, что BeanShell - это то, что вы можете использовать. BeanShell является переводчиком. Вы можете запустить некомпилированный Java-код (поэтому вы даете ему строку с кодом, и он запускает ее).
Конечно, если вы действительно хотите делать то, что вы написали, машине, на которой запущена программа, нужен JDK для компиляции вашей программы.
Надеюсь, что это поможет
Ответ 7
Я не думаю, что он будет работать на Java. Не будет ли это связано с перезаписью запущенного файла класса.
Предположим, что ваша программа находится в Quine.java, скомпилированном в Quine.class.
Теперь Quine.class попытается записать свой вывод в Quine.java(пока это так хорошо) и скомпилировать его в Quine.class. Это будет проблемой, поскольку Quine.class уже запущен
Ответ 8
Да - не забудьте использовать JDK вместо JRE:
-
Свяжите файлы исходного кода приложения с приложением. Приложение скопирует исходные файлы в новый набор файлов исходного кода, скомпилирует новые исходные файлы, свяжет новый исходный код с новыми файлами классов в новое приложение, а затем создаст новое приложение.
или
-
Свяжите декомпилятор с приложением. Приложение будет запускать декомпилятор в своих собственных файлах классов для генерации новых файлов исходного кода, компиляции новых исходных файлов, связывания декомпилятора с новыми файлами классов в новом приложении и последующего появления нового приложения.