现在我们可以用jdk6 的compiler api(jsr 199)去动态编译java源文件,compiler api结合反射功能就可以实现动态的产生java代码并编译执行这些代码,有点动态语言的特征。这个特性对于某些需要用到动态编译的应用程序相当有用, 比如jsp web server,当我们手动修改jsp后,是不希望需要重启web server才可以看到效果的,这时候我们就可以用compiler api来实现动态编译jsp文件,当然,现在的jsp web server也是支持jsp热部署的,现在的jsp web server通过在运行期间通过runtime.exec或processbuilder来调用javac来编译代码,这种方式需要我们产生另一个进程去做编译工作,不够优雅而且容易使代码依赖与特定的操作系统;compiler api通过一套易用的标准的api提供了更加丰富的方式去做动态编译,而且是跨平台的。 下面代码演示了compiler api的使用:
| public class compilerapitester { private static string java_source_file = "dynamicobject.java"; private static string java_class_file = "dynamicobject.class"; private static string java_class_name = "dynamicobject"; public static void main(string[] args) { javacompiler compiler = toolprovider.getsystemjavacompiler(); standardjavafilemanager filemanager = compiler.getstandardfilemanager(null, null, null); generatejavaclass(); try { //将产生的类文件拷贝到程序的classpath下面,下面这一行代码是特定于windows+intellij idea 6.0项目,不具有移植性 runtime.getruntime().exec("cmd /c copy "+java_class_file+" classes//production//jdk6features"); iterable<? extends javafileobject> sourcefiles = filemanager.getjavafileobjects(java_source_file); compiler.gettask(null, filemanager, null, null, null, sourcefiles).call(); filemanager.close(); class.forname(java_class_name).newinstance();//创建动态编译得到的dynamicobject类的实例 } catch (exception ex) { ex.printstacktrace(); } } public static void generatejavaclass(){ try { filewriter fw = new filewriter(java_source_file); bufferedwriter bw = new bufferedwriter(fw); bw.write("public class "+java_class_name+"{"); bw.newline(); bw.write("public "+java_class_name+"(){system.out.println(/"in the constructor of dynamicobject/");}}"); bw.flush(); bw.close(); } catch (ioexception ex) { ex.printstacktrace(); } } } |
程序运行后,会产生dynamicobject.java和dynamicobject.class两个文件,并在控制台输出:
in the constructor of dynamicobject
闽公网安备 35060202000074号