How to programmatically generate .class files?

南楼画角 提交于 2019-12-21 04:12:06

问题


I would like to write a compiler for a toy-language for Java. I would like to generate runnable .class files. I was wondering what is the best library or tool available for doing this? I know I could learn the binary format for all the instructions and build my own constant pool etc, but that seems like work that ought to have been already done: no point reinventing the wheel, right?

Searching online I've found two different Java Assembly languages, Jasmin and Jamaica, however only Jasmin looks somewhat maintained.

Is there a Java library for writing byte codes to a stream? Is this what the Apache BCEL is?

Is their a tool for this that is the "standard" for byte-code generation, like Antlr is for parsing?


PS- The toy language is Brainf***, I wanted something where I could have a simple "grammar" so I could focus on the generation aspect and not the parsing part... that will come later on the next step.


回答1:


ASM and BCEL do basically similar things. I'd recommend ASM as it's much more supported, much smaller, and is up to date JDK-wise.




回答2:


It sounds like you're looking for Apache BCEL:

The Byte Code Engineering Library (Apache Commons BCEL™) is intended to give users a convenient way to analyze, create, and manipulate (binary) Java class files (those ending with .class).




回答3:


JDK 1.6 has the ability to dynamically compile Java classes (see getSystemJavaCompiler). This can be used to compile Java from source without byte code manipulation or temporary files. We're doing this as a way to improve the performance of some reflection API code, but it will just as easily serve your purpose as well.

Create a Java source file from a string containing the code:

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

Then you load the newly created class files dynamically.

Alternatively, use byte code manipulation (such as ASM) to create classes on the fly.

As another alternative, there is the Scala CAFEBABE bytecode compilation library. I have not used it personally, but it seems geared more towards creating a new JVM language.

As far as the parsing portion goes, Antlr should serve.




回答4:


Easiest would be to translate your toy-language into valid .java source code using a preprocessor and then just compile it with javac. That's also the way Processing works.



来源:https://stackoverflow.com/questions/8195507/how-to-programmatically-generate-class-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!