我想为Java的玩具语言编写一个编译器。我想生成可运行的.class文件。我想知道什么是最好的图书馆或工具?我知道我可以学习所有指令的二进制格式并构建我自己的常量池等,但这似乎应该已经完成的工作:没有意义重新发明轮子,对吗?
在线搜索我发现了两种不同的Java汇编语言,Jasmin和Jamaica,但只有Jasmin看起来有点维护。
是否有用于将字节代码写入流的Java库?这是Apache BCEL是什么?
他们的工具是否是字节码生成的“标准”,就像Antlr用于解析一样?
答案 0 :(得分:9)
答案 1 :(得分:3)
听起来你正在寻找Apache BCEL:
字节代码工程库(Apache Commons BCEL™)旨在为用户提供分析,创建和操作(二进制)Java类文件(以.class结尾的文件)的便捷方式。
答案 2 :(得分:2)
JDK 1.6能够动态编译Java类(参见getSystemJavaCompiler)。这可用于从源代码编译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();
然后动态加载新创建的类文件。
或者,使用字节码操作(例如ASM)来动态创建类。
作为另一种选择,有Scala CAFEBABE bytecode compilation library。我没有亲自使用它,但似乎更倾向于创建一种新的JVM语言。
就解析部分而言,Antlr应该服务。
答案 3 :(得分:0)
最简单的方法是使用预处理器将您的玩具语言翻译成有效的.java源代码,然后使用javac进行编译。这也是Processing的工作方式。