打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
在程序中实现对java源文件编译的3种方法
一般情况下对java源文件的编译均是在代码完成后使用javac编译的,不管是使用 IDE还是直接使用命令行。这里要说的情况是比较特别的,就是在代码内动态的编译一些代码。比如你想通过在某个目录下通过放置一些源代码的方式来实现对程序功能的动态扩展,那么你的程序就需要具有一种对源代码的编译、加载、运行的能力,可能就需要本文介绍的3种方法。方法1:通过调用本机的javac命令来编译。在java程序中调用javac命令可以通过调用Runtime类的exec或是ProcessBuilder类的start方法来完成,这两个类的功能基本相同,用法也比较相似,这里的例子我们就用ProcessBuilder来演示。如果是JDK1.5之前的版本请使用Runtime类完成相同的功能。开始之前先来点准备工作,将下面的类放到 c:\mytest\src\ 目录下,这个类我们不会在IDE中编译,而是由我们程序完成其编译。保存时使用UTF-8格式。可以直接在附件中下载这个类。Java代码 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]public class HelloWorld { public void sayHello(String in) { System.out.println("动态编译成功"); System.out.println("使用编译方式:" + in); } } public class HelloWorld { public void sayHello(String in) { System.out.println("动态编译成功"); System.out.println("使用编译方式:" + in); }}准备工作完成,下面就看一下我们程序的代码,这里只列出主要代码Java代码 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 设置javac的编译参数,使用-encoding指定编码方式,-d并指定编译生成class文件目录 ProcessBuilder pb = new ProcessBuilder("javac","-encoding", "UTF-8","-d", binDir, filePath); try { // 开始调用javac命令编译 final Process proc = pb.start(); // 处理进程的输出,避免挂死 new Thread(new Runnable() { public void run() { processStream(proc.getInputStream()); processStream(proc.getErrorStream()); } }).start(); // 等待编译完成 proc.waitFor(); // 加载编译好的类,并调用相应的方法 new LoaderClassByDir(binDir).execSayHello("javac"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } } private static void processStream(InputStream stderr) { ... } } public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 设置javac的编译参数,使用-encoding指定编码方式,-d并指定编译生成class文件目录 ProcessBuilder pb = new ProcessBuilder("javac","-encoding", "UTF-8","-d", binDir, filePath); try { // 开始调用javac命令编译 final Process proc = pb.start(); // 处理进程的输出,避免挂死 new Thread(new Runnable() { public void run() { processStream(proc.getInputStream()); processStream(proc.getErrorStream()); } }).start(); // 等待编译完成 proc.waitFor(); // 加载编译好的类,并调用相应的方法 new LoaderClassByDir(binDir).execSayHello("javac"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } } private static void processStream(InputStream stderr) { ... }}LoaderClassByDir类的代码会保含在后面的上传的文件中,因为这里主要介绍完成程序中对java源文件的编译,对于类的加载和运行不多做描述,可以参考LoaderClassByDir类中的简单实现。方法2:使用Sun的tools.jar包时的com.sun.tools.javac.Main类完成对代码的编译。注意这个类的是在tools.jar包里,tools.jar不是标准的Java库,在使用时必须要设置这个jar的路径,使用IDE时需要显示的引入到编译路径中,不然会找不到。我们使用此类改写上面的编译类如下:Java代码 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 将编译参数通过数组传递到编译方法中,该函数的方法和javac的参数完成一致 Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath}); try { // 加载编译好的类,并调用相应的方法 new LoaderClassByDir(binDir).execSayHello("sun tools"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } } } public class JavacCompile { private static String filePath = "c:\\mytest\\src\\HelloWorld.java"; private static String binDir = "c:\\mytest\\bin"; public static void main(String[] args) { File binOutDir = new File(binDir); if (!binOutDir.exists()) { binOutDir.mkdirs(); } // 将编译参数通过数组传递到编译方法中,该函数的方法和javac的参数完成一致 Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath}); try { // 加载编译好的类,并调用相应的方法 new LoaderClassByDir(binDir).execSayHello("sun tools"); } catch (Exception ex) { Logger.getLogger(JavacCompile.class.getName()).log(Level.SEVERE, null, ex); } }}使用这个类后,同样的功能代码变得更加简洁。方法3:使用javax.tools包从上面可以看到方法2的缺点就是tools.jar需要我们自行导入。而在Java SE6中为我们提供了标准的包来操作Java编译器,这就是javax.tools包。使用这个包,我们可以不用将jar文件路径添加到 classpath中了。 使用这个类的方法和上面的类很相似,我只需要将Java代码 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath}); Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath});替换成:Java代码 [img]http://devbbs.doit.com.cn/attachments/images/302-icon_copy.gif[/img]// 将编译参数通过数组传递到编译方法中,该函数的方法和javac的参数完成一致 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compiler.run(null, null, null, "-encoding", "UTF-8","-d", binDir, filePath); // 将编译参数通过数组传递到编译方法中,该函数的方法和javac的参数完成一致 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compiler.run(null, null, null, "-encoding", "UTF-8","-d", binDir, filePath);就可以完成相应的编译功能,这里简介一下run的使用方法:注意:使用上传文件中的代码做测试时,为避免上次编译的影响记得手动删除C:\mytest\bin下的类文件
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java SE6调用Java编译器的两种新方法
Java程序编译和运行的过程
浅谈为什么一个java源文件中只能有一个public类?
Ubuntu10.04上编译Android源码(Build Android source in Ubuntu10.04 Platform)
Java SE 6 新特性: 编译器 API
java动态编译执行
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服