从字符串编译Java源代码?

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

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

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

这样的事情存在吗?

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

他们自Java 1.6以来一直存在。

这是一些示例代码。

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

您需要的是一个扩展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; } } 

可以使用如下:

 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 fileObjects = Arrays.asList( jsfs); List options = new ArrayList(); 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); } 

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

你可以尝试我的精华jcf库来做到这一点。 在调试中运行时,可以将源写入文件,以便您可以进入代码。 否则,它会在内存中完成所有操作。 它将JavaCompiler包装在tools.jar中

它需要一个String,编译并将其加载到当前的类加载器中并返回Class。 它处理嵌套/内部类。

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

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

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

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

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