Java 如何以编程方式生成.class文件?

Java 如何以编程方式生成.class文件?,java,compiler-construction,jvm,.class-file,Java,Compiler Construction,Jvm,.class File,我想为Java的玩具语言编写一个编译器。我想生成可运行的.class文件。我想知道做这件事最好的库或工具是什么?我知道我可以学习所有指令的二进制格式,并构建自己的常量池等,但这似乎是应该已经完成的工作:没有必要重新发明轮子,对吗 在网上搜索时,我发现了两种不同的Java汇编语言,然而,只有Jasmin看起来有点维护 是否有一个Java库用于将字节码写入流?这就是问题所在吗 他们的工具是否是字节码生成的“标准”工具,就像Antlr用于解析一样 PS-玩具语言是,我想要一些我可以有一个简单的“语法

我想为Java的玩具语言编写一个编译器。我想生成可运行的.class文件。我想知道做这件事最好的库或工具是什么?我知道我可以学习所有指令的二进制格式,并构建自己的常量池等,但这似乎是应该已经完成的工作:没有必要重新发明轮子,对吗

在网上搜索时,我发现了两种不同的Java汇编语言,然而,只有Jasmin看起来有点维护

是否有一个Java库用于将字节码写入流?这就是问题所在吗

他们的工具是否是字节码生成的“标准”工具,就像Antlr用于解析一样



PS-玩具语言是,我想要一些我可以有一个简单的“语法”的东西,这样我可以专注于生成方面,而不是解析部分。。。这将在下一步的后面进行。

听起来您正在寻找:

字节码工程库(Apache Commons BCEL)™) 旨在为用户提供一种方便的方法来分析、创建和操作(二进制)Java类文件(以.class结尾的文件)


最简单的方法是使用预处理器将您的玩具语言翻译成有效的.java源代码,然后用javac编译。这也是可行的方法。

并且做基本类似的事情。我推荐ASM,因为它支持得更多,更小,并且是最新的JDK版本。

JDK1.6具有动态编译的能力Java类(请参阅)。这可以用于从源代码编译Java,而无需字节码操作或临时文件。我们这样做是为了提高某些反射API代码的性能,但它也可以轻松满足您的需要

从包含以下代码的字符串创建Java源文件:

   public class JavaSourceFromString extends SimpleJavaFileObject {
       final String code;

       JavaSourceFromString(String name, String code) {
           super(URI.create("string:///"
                            + name.replace('.','/')
                            + Kind.SOURCE.extension),
                 Kind.SOURCE);
           this.code = code;
       }

       @Override
       public CharSequence getCharContent(boolean ignoreEncodingErrors) {
           return code;
       }
   }

// Use your favorite template language here, like FreeMarker
static final String sourceCode = ""
        + "import org.example.MySomethingObject;"
        // DynamicStringGetter would define getString as a standard way to get
        // a String from an object
        + "public class GetStringDynamic implements DynamicStringGetter {\n" 
        + "    public String getString(Object o) {\n"
        + "        MySomethingObject obj = (MySomethingObject) o;\n"
        + "        return o.getSomething();\n"
        + "    }\n"
        + "}\n";

   JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
   StandardJavaFileManager fileManager = 
       compiler.getStandardFileManager(null, null, null);

   List<JavaFileObject> files = new ArrayList<JavaFileObject>();
   files.add(new JavaSourceFromString("org.example.DynamicClass", sourceCode));

   compiler.getTask(null, fileManager, null, null, null, files).call();
公共类JavaSourceFromString扩展了SimpleJavaFileObject{
最终字符串代码;
JavaSourceFromString(字符串名称、字符串代码){
super(URI.create(“字符串://”)
+名称.替换('.','/'))
+种类,来源,外延),,
种类(来源);
this.code=代码;
}
@凌驾
public CharSequence getCharContent(布尔ignoreEncodingErrors){
返回码;
}
}
//在这里使用您最喜欢的模板语言,如FreeMarker
静态最终字符串sourceCode=“”
+“导入org.example.MySomethingObject;”
//DynamicStringGetter将getString定义为获取
//来自对象的字符串
+“公共类GetStringDynamic实现DynamicStringGetter{\n”
+“公共字符串getString(对象o){\n”
+“MySomethingObject obj=(MySomethingObject)o;\n”
+“返回o.getSomething();\n”
+“}\n”
+“}\n”;
JavaCompiler=ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager文件管理器=
编译器.getStandardFileManager(null,null,null);
列表文件=新的ArrayList();
add(新的JavaSourceFromString(“org.example.DynamicClass”,sourceCode));
getTask(null,fileManager,null,null,null,files).call();
然后动态加载新创建的类文件

或者,使用字节码操作(例如)动态创建类

作为另一种选择,还有。我没有亲自使用它,但它似乎更倾向于创建一种新的JVM语言


就解析部分而言,Antlr应该可以使用。

我倾向于使用ASM,但它的级别可能太低。ASM用于Java字节码还是生成本机代码?Objectweb的ASM库。它不像某些库那么容易使用,但我喜欢低级别的方法。@Ira Baxter实现BF很容易,这就是我开始使用它的原因它。我用它作为学习工具的借口。我看了一下,1)我不知道这是否符合我的要求,2)这是否是首选工具。我真的很想听到有人真的这样做了,并可以证明一个工具。@ArtB:如果你说你看到了它,那会有帮助的。。。我自己也没用过,但我确实听说过它的好处。您可能还想看看我已经看过了它和CGLib,CGLib看起来像是专注于运行时操作。BCEL我现在正在浏览这取决于玩具语言是否可以轻松地翻译成Java。许多语言都有几种编译器可以编译成字节码,但为Java翻译它们将是一项具有挑战性的任务。使用其他语言(即使是基于JVM的语言)的原因之一就是为了绕过这个限制。它甚至可以用来生成独立的类文件,还是只能用于内存编译?此外,玩具语言比Java低级得多,这使得翻译很难。@ArtB是的,它可以生成独立的类文件,或者根据您对FileManager的操作,这些类可以保存在内存中。我们只是将类存储在内存中,因为出于我们的目的,它们是短暂的。玩具语言的一个例子可能有助于确定适合性。通常,生成Java源代码要比确定字节码容易,但如果您在向VM添加新语言的过程中做得更多,则可能会有些过火。另一方面,使用源代码参考Java库很容易。本练习的全部目的是学习工具,因此确定字节码。@ArtB Fairy nuff。我建议使用ASM或我上面链接的Scala。非常感谢上面的代码示例!它似乎对我有用,但它正在我的项目根目录中生成一个.class文件。有没有办法只将生成的.class文件作为字节[]检索,而不是写入文件?或者,指定.class文件应该写入的位置?