有没有办法让正在运行的Java程序编译Java源代码(以字符串形式传递)?
Class newClass = Compiler.compile ("class ABC { void xyz {etc. etc. } }");
理想情况下,传入源代码引用的任何类都将由程序的类加载器解析。
这样的事情是否存在?
答案 0 :(得分:9)
不确定。查看JavaCompiler
类以及javax.tools
包中的其他类。
他们自Java 1.6以来一直存在。
(正如@Sergey Tachenov在评论中指出的那样,它需要安装JDK作为必要的tools.jar文件随JDK一起提供而不是JRE。)
答案 1 :(得分:4)
您需要的是一个扩展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<? 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);
}
答案 2 :(得分:3)
取决于你想做什么。 如果您只想运行一些代码,可以使用BeanShell。它不是一个java编译的类,但是非常有用,可以使一些灵活的东西
答案 3 :(得分:1)
你可以试试我的精华jcf库来做到这一点。在调试中运行时,可以将源写入文件,以便您可以单步执行代码。否则,它会在内存中完成所有操作。它将JavaCompiler包装在tools.jar
中它接受一个String,编译并将其加载到当前的类加载器中并返回Class。它处理嵌套/内部类。
http://vanillajava.blogspot.com/2010/11/more-uses-for-dynamic-code-in-java.html
注意:我没有在OSGi中使用它。 ;)
答案 4 :(得分:1)
Javassist可以从源代码的Strings生成并加载运行时类和方法。 如果需要,也可以在文件系统中转储生成的类。
目前,您可以在这些字符串中传递的代码存在一些小的限制,例如,它不能包含泛型,枚举或自动装箱以及基元的收件箱。 更多信息: