能够自我复制的程序

发布于 2024-08-28 15:02:23 字数 59 浏览 9 评论 0原文

是否可以制作一个 Java 程序,将其源代码打印到一个新文件中,然后对其进行编译,然后运行编译后的程序?

Is it possible to make a Java program that prints its source code to a new file, and compiles it, and runs the compiled program?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

小红帽 2024-09-04 15:02:23

更新:

好的,不妨让它自动运行。享受疯狂。运行风险自负。


是的,这是可能的,因为我确实写了它。 它不执行 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]

更新:

好的,不妨让它自动运行。享受疯狂。运行风险自负。


是的,这是可能的,因为我确实写了它。 它不执行 RUN 部分(这太疯狂了,因为正如其他人提到的,它会导致无限循环), 但这里是:Quine.java

; 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 的区别在于格式化和 3x 替换次要差异是 Quine$.javaout 设置为 Quine$$
  • Quine$ 将生成、编译并运行 Quine$$
  • Quine$$ 将生成、编译并运行 Quine$$$Quine$$ 将生成、编译并运行 Quine$$$ code>
  • Quine$$$ 将生成、编译并运行 Quine$$$$
  • ...

请注意,这不会通过阅读进行任何逆向工程或作弊.java 源代码等。 Quine 是一个 quine 生成器,因为它生成不同格式的不同代码,但 Quine$ 几乎是一个真正的独立的 quine:它确实会自我复制,只是重新标记它 Quine$$ (它会自我复制并重新标记为 Quine$$$ 等)。

因此从技术上讲,不存在无限循环:当文件系统无法处理另一个 $ 时,它最终会停止。 我能够通过强制删除所有 Quine$* 文件来手动阻止这种疯狂行为,但运行风险需要您自担!!!

Update:

Okay, might as well make it autorun. Enjoy the madness. Run at your own risk.


Yes it's possible, because I actually wrote it up. It doesn't do the RUN part (that's just too crazy, because as others have mentioned, it will cause an infinite loop), but here it is: 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]

Update:

Okay, might as well make it autorun. Enjoy the madness. Run at your own risk.


Yes it's possible, because I actually wrote it up. It doesn't do the RUN part (that's just too crazy, because as others have mentioned, it will cause an infinite loop), but here it is: Quine.java

; 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); } }

So here's how to get the craziness to start:

  • javac Quine.java to compile
  • java Quine to run it
    • It will produce, compile and run Quine$
  • I've made sure Quine.java is as readable as possible, so the major difference from Quine$.java are formatting and the 3x replace. The minor difference is that Quine$.java has out set to Quine$$.
  • Quine$ will produce, compile and run Quine$$
  • Quine$$ will produce, compile and run Quine$$$
  • Quine$$$ will produce, compile and run Quine$$$$
  • ...

Do note that this doesn't do any reverse-engineering or cheat by reading the .java source code, etc. Quine is a quine-generator because it produces a different code differently formatted, but Quine$ is pretty much a true self-contained quine: it does reproduce itself, it just relabels it Quine$$ (which reproduces itself and relabels to Quine$$$ etc).

So technically there's no infinite loop: it will eventually come to a halt when the file system can't handle another $. I was able to manually stop the madness by forcefully deleting all Quine$* files, but run at your own risk!!!

手心的温暖 2024-09-04 15:02:23

是的,这是可能的。
一个简单的实现是:让源代码将其自身包含在一个字符串中,将该字符串保存到一个文件中,并用相同的字符串填充它自己的字符串(否则,由于这种递归方式,初始字符串将具有无限大小)实现),编译该文件,并运行编译后的文件(反过来,这将执行相同的操作)。

重要的实现要困难得多。

Yes, it is possible.
A trivial implementation would be: have the source code contain itself in a string, save the string to a file and fill its own string with the same string (otherwise, the initial string would be of infinite size, due to the recursive manner of this implementation), compile the file, and run the compiled file (which will, in turn, do the very same).

Non-trivial implementations are significantly harder.

意中人 2024-09-04 15:02:23

当然可以 - 查看 rosetta 代码 并导航到 Quine,这是一个自无需任何外部访问即可输出其自己的源代码的参考程序。

Java 中有一个 quine 的例子。

Sure it works - Have a look at rosetta code and navigate to Quine, which is a self-referential program that can, without any external access, output its own source.

There's one example for a quine in Java.

吃素的狼 2024-09-04 15:02:23

自我复制或自我复制程序被称为Quine 程序 < /p>

示例程序位于 < 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);}} 

Programs that reproduces itself or Self Replicating Programs are known as Quine Programs

Sample Program in Java which reproduces itself.

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);
     }

}

Output:

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);}} 
耶耶耶 2024-09-04 15:02:23

为此,您可以使用 Java 编译器 API (JSR-199)。下面是来自 JSR-199 的代码,该代码从字符串编译代码(稍微修改以使其编译)。该代码实际上将源代码从 String 编译为字节数组(即它不写入磁盘),加载它,然后通过反射执行它:

这可能是一个起点(归功于原作者 Peter Van der Ahé)。

顺便说一句,您当然需要 JDK 才能使用此 API。

You could use the Java Compiler API (JSR-199) for this. Below, code from the JSR-199 that compiles code from a String (slightly modified to make it compile). The code actually compiles source code from the String into a byte array (i.e. it doesn't write to disk), loads it and then executes it via reflection:

That could be a starting point (credits to Peter Van der Ahé, the original author).

BTW, you need of course a JDK to use this API.

最偏执的依靠 2024-09-04 15:02:23

我不知道你到底想要什么,但我认为 BeanShell 是你可以使用的东西。
BeanShell 是一个解释器。您可以运行未编译的 Java 代码(因此您给它一个带有代码的字符串,然后他运行它)。

当然,如果你真的想做你写的事情,运行程序的机器需要有JDK来编译你的程序。

希望这有帮助

I don't know exactly what you want, but I think BeanShell is something you can use.
BeanShell is an interpreter. You can run uncompiled Java-code (So you give it a String with code and he runs it).

Of course if you really want to do what you wrote, the machine where the program is running needs a JDK to compile your program.

Hope this helps

街角迷惘 2024-09-04 15:02:23

我认为它在 Java 中不起作用。这不会涉及覆盖正在运行的类文件吗?

假设你的程序在Quine.java中编译为Quine.class。

现在Quine.class将尝试将其输出写入Quine.java(到目前为止一切顺利),并将其编译为Quine.class。这将是一个问题,因为 Quine.class 已经在运行

I dont think it will work in Java. Wouldn't that involve overwriting a running class file.

Suppose your program is in Quine.java compiled to Quine.class.

Now Quine.class will attempt to write its output to Quine.java (so far so good), and compile it to Quine.class. This is gonna be a problem as Quine.class is already running

满地尘埃落定 2024-09-04 15:02:23

是的 - 不要忘记使用 JDK 而不是 JRE:

  1. 将应用程序的源代码文件与应用程序捆绑在一起。该应用程序会将源文件复制到一组新的源代码文件,编译新的源文件,将新的源代码与新的类文件捆绑到一个新的应用程序中,然后生成新的应用程序。

  2. 将反编译器与应用程序捆绑在一起。该应用程序将在自己的类文件上运行反编译器以生成新的源代码文件,编译新的源文件,将反编译器与新的类文件捆绑到新应用程序中,然后生成新应用程序。

Yes - don't forget to use a JDK instead of a JRE:

  1. Bundle the app's source code files with the app. The app would copy the source files to a new set of source code files, compile the new source files, bundle the new source code with the new class files into a new app, and then spawn the new app.

    or

  2. Bundle a decompiler with the app. The app would run the decompiler on its own class files to generate new source code files, compile the new source files, bundle the decompiler with the new class files into a new app, and then spawn the new app.

走走停停 2024-09-04 15:02:23

这是一个使用预览文本块功能 (-source 13 --enable-preview) 的 Java Quine,其中输出的格式与输入相同:

package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f ="""
package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f =""%c%c%s%1$c"";
    System.out.printf(f, 34, 10, f);
  }
}
""";
    System.out.printf(f, 34, 10, f);
  }
}

输出:

package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f ="""
package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f =""%c%c%s%1$c"";
    System.out.printf(f, 34, 10, f);
  }
}
""";
    System.out.printf(f, 34, 10, f);
  }
}

大量评论版本:

package org.sample.quine;

public class Quine
{
  public static void main(String...args)
  {
    // Inside text block use "" followed by token or token followed by "" so that we don't prematurely close text block
    String f ="""
package org.sample.quine;

public class Quine
{
  public static void main(String...args)
  {
    // Inside text block use "" followed by token or token followed by "" so that we don't prematurely close text block
    String f =""%c%c%s%1$c"";
    /* Tokens in template text block, each prefixed with percent symbol
     * 1(c)   third quote (34) of open block delimiter
     * 2(c)   new line    (10) of open block delimiter
     * 3(s)   String f         text block that goes between two text block delimiters
     * 4(1$c) first quote (34) of close block delimiter,
     *        1$ means first argument after template argument
     *        2$ would be second argument after template argument
     */
     // Arguments - 1 template (String f); 2 "; 3 newline; 4 template again without replacing tokens
     System.out.printf(f, 34, 10, f);
  }
}
""";
    /* Tokens in template text block, each prefixed with percent symbol
     * 1(c)   third quote (34) of open block delimiter
     * 2(c)   new line    (10) of open block delimiter
     * 3(s)   String f         text block that goes between two text block delimiters
     * 4(1$c) first quote (34) of close block delimiter,
     *        1$ means first argument after template argument
     *        2$ would be second argument after template argument
     */
    // Arguments - 1 template (String f); 2 "; 3 newline; 4 template again without replacing tokens
    System.out.printf(f, 34, 10, f);
  }
}

Here's a Java Quine using preview text block feature (-source 13 --enable-preview) where output is formatted the same as input:

package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f ="""
package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f =""%c%c%s%1$c"";
    System.out.printf(f, 34, 10, f);
  }
}
""";
    System.out.printf(f, 34, 10, f);
  }
}

Output:

package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f ="""
package org.sample.quine;

public class QuineProgram
{
  public static void main(String...args)
  {
    String f =""%c%c%s%1$c"";
    System.out.printf(f, 34, 10, f);
  }
}
""";
    System.out.printf(f, 34, 10, f);
  }
}

Heavily Commented Version:

package org.sample.quine;

public class Quine
{
  public static void main(String...args)
  {
    // Inside text block use "" followed by token or token followed by "" so that we don't prematurely close text block
    String f ="""
package org.sample.quine;

public class Quine
{
  public static void main(String...args)
  {
    // Inside text block use "" followed by token or token followed by "" so that we don't prematurely close text block
    String f =""%c%c%s%1$c"";
    /* Tokens in template text block, each prefixed with percent symbol
     * 1(c)   third quote (34) of open block delimiter
     * 2(c)   new line    (10) of open block delimiter
     * 3(s)   String f         text block that goes between two text block delimiters
     * 4(1$c) first quote (34) of close block delimiter,
     *        1$ means first argument after template argument
     *        2$ would be second argument after template argument
     */
     // Arguments - 1 template (String f); 2 "; 3 newline; 4 template again without replacing tokens
     System.out.printf(f, 34, 10, f);
  }
}
""";
    /* Tokens in template text block, each prefixed with percent symbol
     * 1(c)   third quote (34) of open block delimiter
     * 2(c)   new line    (10) of open block delimiter
     * 3(s)   String f         text block that goes between two text block delimiters
     * 4(1$c) first quote (34) of close block delimiter,
     *        1$ means first argument after template argument
     *        2$ would be second argument after template argument
     */
    // Arguments - 1 template (String f); 2 "; 3 newline; 4 template again without replacing tokens
    System.out.printf(f, 34, 10, f);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文