代码之家  ›  专栏  ›  技术社区  ›  Ming-Tang

自我复制的程序

  •  16
  • Ming-Tang  · 技术社区  · 14 年前

    是否有可能生成一个Java程序,将其源代码打印到一个新文件中,并编译它,并运行编译程序?

    8 回复  |  直到 8 年前
        1
  •  11
  •   M.A. Hanin    14 年前

    是的,这是可能的。 一个简单的实现是:将源代码包含在一个字符串中,将该字符串保存到一个文件中,并用相同的字符串填充它自己的字符串(否则,由于此实现的递归方式,初始字符串的大小将是无限的),编译该文件,然后运行编译后的文件(这反过来又会做非常相同的事情)。

    非平凡的实现非常困难。

        2
  •  22
  •   polygenelubricants    14 年前

    更新:

    好吧,不妨让它自动运行。享受疯狂。自己承担风险。


    是的,这是可能的,因为我确实写了。 它不执行运行部分(这太疯狂了,因为正如其他人提到的,它将导致无限循环)。 但这里是: 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 正在格式化和3x replace . 这个 少数的 区别在于 奎因$JAVA out 设置为 Quine$$ .
    • 奎因$ 将生成、编译和运行 奎因$ $
    • 奎因$ $ 将生成、编译和运行 Quine$$$
    • 奎因$ $ $ 将生成、编译和运行 Quine$$$$

    请注意,这不会做任何逆向工程或通过阅读 .java 源代码等。 Quine 是Quine生成器,因为它生成的代码格式不同,但是 奎因$ 几乎是一种真正的自给自足的奎因:它确实能自我复制,只是重新标记它。 奎因$ $ (它自己复制并转载给 奎因$ $ $ 等)。

    所以从技术上讲,没有无限循环:当文件系统无法处理另一个循环时,它最终会停止。 $ . 我可以通过强制删除所有 Quine$* 文件,但请自行承担风险!!!!

        3
  •  6
  •   Andreas Dolk    14 年前

    当然可以-看看 rosetta code 导航到Quine,也就是 一种无需任何外部访问就可以输出自己的源的自引用程序。 .

    Java中有一个奎因的例子。

        4
  •  4
  •   09Q71AO534    9 年前

    自我复制或自我复制的程序称为 Quine Programs

    示例程序输入 爪哇 它可以自我复制。

    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
  •  2
  •   Pascal Thivent    14 年前

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

    这可能是一个起点(归功于原作者彼得·范德阿)。

    顺便说一句,使用这个API当然需要一个JDK。

        6
  •  1
  •   Martijn Courteaux    14 年前

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

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

    希望这有帮助

        7
  •  0
  •   Midhat    14 年前

    我认为它不会用Java工作。这不包括重写正在运行的类文件吗?

    假设您的程序是在quine.java中编译为quine.class。

    现在quine.class将尝试将其输出写入quine.java(目前为止还不错),并将其编译为quine.class。这将是一个问题,因为quine.class已经在运行了

        8
  •  0
  •   Bert F    14 年前

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

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

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