java 从字符串编译Java源代码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4463440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:30:33  来源:igfitidea点击:

Compile Java source code from a string?

javacompiler-construction

提问by Tony the Pony

Is there a way for a running Java program to compile Java source code (passed as a string)?

有没有办法让正在运行的 Java 程序编译 Java 源代码(作为字符串传递)?

Class newClass = Compiler.compile ("class ABC { void xyz {etc. etc. } }");

Ideally, any classes referenced by the passed-in source code would be resolved by the program's class loader.

理想情况下,传入源代码引用的任何类都将由程序的类加载器解析。

Does something like this exist?

这样的东西存在吗?

回答by aioobe

Sure. Have a look at the JavaCompilerclass and the other classes in the javax.toolspackage.

当然。查看包中的JavaCompiler类和其他类javax.tools

They've been around since Java 1.6.

它们从 Java 1.6 开始就存在了。

Here is some example code.

这是一些示例代码。

(As pointed out by @Sergey Tachenov in the comments, it needs JDK to be installed as the necessary tools.jar file comes with JDK but not JRE.)

(正如@Sergey Tachenov 在评论中指出的,它需要安装 JDK,因为必要的 tools.jar 文件随 JDK 而不是 JRE。)

回答by MonoThreaded

What you need is a class that extends JavaFileObject

你需要的是一个扩展 JavaFileObject 的类

import java.net.URI;

import javax.tools.SimpleJavaFileObject;

public class JavaSourceFromString extends SimpleJavaFileObject {
    final String code;

    public 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;
    }
}

Which can be used as follows:

可以按如下方式使用:

JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
if( jc == null) throw new Exception( "Compiler unavailable");

String code = "public class CustomProcessor { /*custom stuff*/ }";
JavaSourceFromString jsfs = new JavaSourceFromString( "CustomProcessor", code);

Iterable<? extends JavaFileObject> fileObjects = Arrays.asList( jsfs);

List<String> options = new ArrayList<String>();
options.add("-d");
options.add( compilationPath);
options.add( "-classpath");
URLClassLoader urlClassLoader =
         (URLClassLoader)Thread.currentThread().getContextClassLoader();
StringBuilder sb = new StringBuilder();
for (URL url : urlClassLoader.getURLs()) {
    sb.append(url.getFile()).append(File.pathSeparator);
}
sb.append( compilationPath);
options.add(sb.toString());

StringWriter output = new StringWriter();
boolean success = jc.getTask( output, null, null, options, null, fileObjects).call(); 
if( success) {
    logger.info( LOG_PREFIX + "Class has been successfully compiled");
} else {
    throw new Exception( "Compilation failed :" + output);
}

回答by Plínio Pantale?o

Depends on what you want to do. If you just want to run some code you could use BeanShell. It's not a java compiled class, but is very usefull to make something flexible

取决于你想做什么。如果你只是想运行一些代码,你可以使用 BeanShell。它不是一个 java 编译的类,但对于使某些东西变得灵活非常有用

回答by Peter Lawrey

You could try my essence jcf library which does this. When running in debug you can have the source written to a file so you can step into the code. Otherwise, it does everything in memory. It wraps the JavaCompiler in tools.jar

你可以试试我的本质 jcf 库,它可以做到这一点。在调试中运行时,您可以将源代码写入文件,以便您可以单步执行代码。否则,它会在内存中执行所有操作。它将 JavaCompiler 包装在 tools.jar 中

It takes a String, compiles and loads it into the current class loader and returns the Class. It handles nested/inner classes.

它接受一个字符串,将其编译并加载到当前的类加载器中并返回该类。它处理嵌套/内部类。

http://vanillajava.blogspot.com/2010/11/more-uses-for-dynamic-code-in-java.html

http://vanillajava.blogspot.com/2010/11/more-uses-for-dynamic-code-in-java.html

Note: I haven't got this working in OSGi. ;)

注意:我还没有在 OSGi 中使用它。;)

回答by Sergio

Javassist can generate and load at runtime classes and methods from Strings of source code. It is also possible to dump in the file system the generated class if you need to.

Javassist 可以在运行时从源代码字符串生成和加载类和方法。如果需要,也可以将生成的类转储到文件系统中。

Currently there are minor limitations in the code you can pass in those strings, for example it cannot include generics, enumerations, or autoboxing and inboxing of primitives. More information here:

目前,您可以在这些字符串中传递的代码有一些小的限制,例如,它不能包含泛型、枚举或基元的自动装箱和收件箱。更多信息在这里:

http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/

http://www.csg.ci.iu-tokyo.ac.jp/~chiba/javassist/