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

时间:2011-11-19 16:37:21

标签: java compiler-construction jvm .class-file

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

在线搜索我发现了两种不同的Java汇编语言,JasminJamaica,但只有Jasmin看起来有点维护。

是否有用于将字节代码写入流的Java库?这是Apache BCEL是什么?

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


PS-玩具语言是Brainf***,我想要一些我可以拥有一个简单的“语法”的东西,所以我可以专注于生成方面而不是解析部分...将在下一个晚些时候出现步骤

4 个答案:

答案 0 :(得分:9)

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

答案 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的工作方式。