`
daimojingdeyu
  • 浏览: 271977 次
  • 性别: Icon_minigender_1
  • 来自: 山东
社区版块
存档分类
最新评论

在程序中实现对java源文件编译的3种方法

    博客分类:
  • Java
阅读更多
一般情况下对java源文件的编译均是在代码完成后使用javac编译的,不管是使用IDE还是直接使用命令行。这里要说的情况是比较特别的,就是在代码内动态的编译一些代码。比如你想通过在某个目录下通过放置一些源代码的方式来实现对程序功能的动态扩展,那么你的程序就需要具有一种对源代码的编译、加载、运行的能力,可能就需要本文介绍的3种方法。

方法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下的类文件

  • HelloWorld.zip (349 Bytes)
  • 描述: 需动态编译的源文件
  • 下载次数: 108
  • src.zip (3.7 KB)
  • 描述: 程序源代码
  • 下载次数: 140
分享到:
评论
2 楼 daimojingdeyu 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引入到编译路径中
1 楼 wubo19842008 2009-10-14  
用javax.tool包编译时,如果源文件依赖外部jar包,如何设置classpath啊?

相关推荐

    在程序中实现对java源文件编译的3种方法.pdf

    在程序中实现对java源文件编译的3种方法.pdf

    在程序中实现对java源文件编译的3种方法文.pdf

    在程序中实现对java源文件编译的3种方法文.pdf

    Java动态编译Java代码,运行在内存中,并执行

    通过java的ToolProvider创建JavaCompile,用来执行class源文件 * 4.创建DiagnosticCollector用来执行获取执行失败的错误结果 * 5.添加动态执行的编译环境 options 是个集合,添加内容,字符集,classpath等 * 6....

    JAVA阶段模拟试题

    8在Java中,源文件Test.java中包含如下代码段,则程序编译运行结果是( )。(选择一项) public class Test{ public static main (String [ ] args) { system.out.print(“Hello!”); } } A输出:...

    xjad java反编译工具

    1、XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2; 2、可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件; 3、带有多页面文本编辑器,也可集成在资源管理器中,随时点击右键...

    java class文件反编译

    1、XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2; 2、可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件; 3、带有多页面文本编辑器,也可集成在资源管理器中,随时点击右键...

    java反编译工具

    1、XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2; 2、可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件; 3、带有多页面文本编辑器,也可集成在资源管理器中,随时点击右键...

    XJad jar包反编译成java源文件工具

    软件介绍: XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2。  XJad可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件。  XJad带有多页面文本编辑器,反编译完成后可以直接...

    java反编译程序.rar

    可将任何java编译的*.class文件编反译成java源文件。 XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2。  XJad可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件。  XJad带有...

    XJad_Java源程序反编译软件

    非常好用的Java源程序反编译软件 1、XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2; 2、可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件; 3、带有多页面文本编辑器,也可...

    java反编译工具(可以集成到eclipse当中)

    可以将class文件反编译成java文件 假设将jad.exe安装在f:\java\jad目录下 把要反编译的文件*.class复制到此目录下,接着接以下步骤, 在命令行窗口环境中进入jad目录, 然后运行:jad -s java *.class (附,*.class...

    Java快速命令编译助手(JCR)

    是我学习Java一段时间后,根据我了解的编译技巧制作的一个可以对Java源文件进行快速编译的小程序。 有了它我们就不必要:开始 输入 cmd 然后再转到当前盘,当前路径,再输入Javac 文件名.Java 也不用输入:Javac ...

    JAVA初学小程序

    该命令用于将 java 源文件编译为 class 字节码文件,如: javac HelloWorld.java。 运行javac命令后,如果成功编译没有错误的话,会出现一个 HelloWorld.class 的文件。 java 后面跟着的是java文件中的类名,例如 ...

    XJad2.2_反编译JAVA

    1、XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2; 2、可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件; 3、带有多页面文本编辑器,也可集成在资源管理器中,随时点击右键...

    命令行下的Java编译工具

    适合初学者用,个人用批处理编写的java编译工具。出于保护版权,转成了exe格式,人格保证,绝对无毒。 本人08年开始接触Java,初学者当然是使用黑框框编译啦,可是JDK编译器手动太麻烦,又要javac源文件,又要java...

    JAVA上百实例源码以及开源项目源代码

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...

Global site tag (gtag.js) - Google Analytics