浏览 4650 次
锁定老帖子 主题:在程序中实现对java源文件编译的3种方法
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-07-18
最后修改:2009-07-24
方法1:通过调用本机的javac命令来编译。
在java程序中调用javac命令可以通过调用Runtime类的exec或是ProcessBuilder类的start方法来完成,这两个类的功能基本相同,用法也比较相似,这里的例子我们就用ProcessBuilder来演示。如果是JDK1.5之前的版本请使用Runtime类完成相同的功能。 开始之前先来点准备工作,将下面的类放到 c:\mytest\src\ 目录下,这个类我们不会在IDE中编译,而是由我们程序完成其编译。保存时使用UTF-8格式。可以直接在附件中下载这个类。 public class HelloWorld { public void sayHello(String in) { System.out.println("动态编译成功"); System.out.println("使用编译方式:" + in); } } 准备工作完成,下面就看一下我们程序的代码,这里只列出主要代码 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时需要显示的引入到编译路径中,不然会找不到。我们使用此类改写上面的编译类如下: 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中了。 使用这个类的方法和上面的类很相似,我只需要将 Main.compile(new String[]{"-encoding", "UTF-8","-d", binDir, filePath}); 替换成: // 将编译参数通过数组传递到编译方法中,该函数的方法和javac的参数完成一致 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compiler.run(null, null, null, "-encoding", "UTF-8","-d", binDir, filePath); 就可以完成相应的编译功能,这里简介一下run的使用方法: 引用 我们可以通过ToolProvider类的静态方法getSystemJavaCompiler来得到一个JavaCompiler接口的实例。
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaCompiler中最核心的方法是run。通过这个方法可以编译java源程序。这个方法有3个固定参数和1个可变参数(可变参数是从 Jave SE5开始提供的一个新的参数类型,用type… argu表示)。前3个参数分别用来为java编译器提供参数、得到Java编译器的输出信息以及接收编译器的错误信息,后面的可变参数可以传入一个或多个Java源程序文件。如果run编译成功,返回0。 int run(InputStream in, OutputStream out, OutputStream err, String... arguments) 如果前3个参数传入的是null,那么run方法将以标准的输入、输出代替,即System.in、System.out和System.err。 注意:使用上传文件中的代码做测试时,为避免上次编译的影响记得手动删除C:\mytest\bin下的类文件 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-10-14
用javax.tool包编译时,如果源文件依赖外部jar包,如何设置classpath啊?
|
|
返回顶楼 | |
发表时间:2009-10-14
wubo19842008 写道 用javax.tool包编译时,如果源文件依赖外部jar包,如何设置classpath啊?
这里的参数设置和javac的参数基本上是一致的,如果想指定classpath,可以指定-cp参数,使用样例如下: int result = compiler.run(null, null, null, "-encoding", "UTF-8", "-cp", "D:/Program Files/Java/jdk1.6.0_14/lib/tools.jar", "-d", binDir, filePath); 如上就可以将sun的tools.jar引入到编译路径中 |
|
返回顶楼 | |