`
daimojingdeyu
  • 浏览: 275320 次
  • 性别: 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啊?

相关推荐

    基于OpenCV的人脸识别小程序.zip

    【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    精选毕设项目-宅男社区.zip

    精选毕设项目-宅男社区

    精选毕设项目-扫描条形码.zip

    精选毕设项目-扫描条形码

    配网两阶段鲁棒优化调度模型 关键词:两阶段鲁棒优化,CCG算法,储能 仿真算例采用33节点,采用matlab+yalmip+cplex编写,两阶段模型采用CCG算法求解 模型中一阶段变量主要包括01

    配网两阶段鲁棒优化调度模型 关键词:两阶段鲁棒优化,CCG算法,储能 仿真算例采用33节点,采用matlab+yalmip+cplex编写,两阶段模型采用CCG算法求解。 模型中一阶段变量主要包括01变量和无功优化变量,核心变量主要存在于二阶段,因此在叠加二阶段变量优化过程中更容易得到最优解,所以有限次迭代即得到收敛的结果。 模型以网损为目标,包括功率平衡、网络潮流、电压电流、蓄电池出力以及无功设备出力等约束。 复现《两阶段鲁棒优化的主动配电网动态无功优化》-熊壮壮,具体内容可自行下载了解。

    comsol光栅仿真 计算复合波导光栅准BIC增强古斯汉森位移

    comsol光栅仿真 计算复合波导光栅准BIC增强古斯汉森位移

    精选毕设项目-车源宝寻车广场.zip

    精选毕设项目-车源宝寻车广场

    数字农业产业项目整体解决方案.pdf

    数字农业产业项目整体解决方案

    精选毕设项目-幸运大抽奖.zip

    精选毕设项目-幸运大抽奖

    SRS构型七自由度冗余机械臂运动学建模全套matlab代码 代码主要功能: 1. 基于臂角参数化方法求解机械臂在给定末端位姿和臂角下的关节角度; 2. 求解机械臂在给定末端位姿下的有效臂角范围

    SRS构型七自由度冗余机械臂运动学建模全套matlab代码 代码主要功能: [1]. 基于臂角参数化方法求解机械臂在给定末端位姿和臂角下的关节角度; [2]. 求解机械臂在给定末端位姿下的有效臂角范围,有效即在该区间内机械臂关节角度不会超出关节限位; [3]. 以避关节限位为目标在有效臂角区间内进行最优臂角的选取,进而获取机械臂在给定末端位姿下的最优关节角度。 购前须知: 1. 代码均为个人手写,主要包含运动学建模全套代码; 2. 代码已经包含必要的注释; 包含原理推导文档,不包含绘图脚本以及urdf;

    精选毕设项目-微信小程序天气源码.zip

    精选毕设项目-微信小程序天气源码

    bmjebm-29-6.pdf

    bmjebm-29-6.pdf

    chromedriver-linux64_123.0.6273.0.zip

    chromedriver-linux64_123.0.6273.0

    精选毕设项目-腾讯云小程序一站式解决方案.zip

    精选毕设项目-腾讯云小程序一站式解决方案

    精选毕设项目-仿饿了么.zip

    精选毕设项目-仿饿了么

    学生宿舍管理系统的设计与开发-springboot毕业项目,适合计算机毕-设、实训项目、大作业学习.zip

    Spring Boot是Spring框架的一个模块,它简化了基于Spring应用程序的创建和部署过程。Spring Boot提供了快速启动Spring应用程序的能力,通过自动配置、微服务支持和独立运行的特性,使得开发者能够专注于业务逻辑,而不是配置细节。Spring Boot的核心思想是约定优于配置,它通过自动配置机制,根据项目中添加的依赖自动配置Spring应用。这大大减少了配置文件的编写,提高了开发效率。Spring Boot还支持嵌入式服务器,如Tomcat、Jetty和Undertow,使得开发者无需部署WAR文件到外部服务器即可运行Spring应用。 Java是一种广泛使用的高级编程语言,由Sun Microsystems公司(现为Oracle公司的一部分)在1995年首次发布。Java以其“编写一次,到处运行”(WORA)的特性而闻名,这一特性得益于Java虚拟机(JVM)的使用,它允许Java程序在任何安装了相应JVM的平台上运行,而无需重新编译。Java语言设计之初就是为了跨平台,同时具备面向对象、并发、安全和健壮性等特点。 Java语言广泛应用于企业级应用、移动应用、桌面应用、游戏开发、云计算和物联网等领域。它的语法结构清晰,易于学习和使用,同时提供了丰富的API库,支持多种编程范式,包括面向对象、命令式、函数式和并发编程。Java的强类型系统和自动内存管理减少了程序错误和内存泄漏的风险。随着Java的不断更新和发展,它已经成为一个成熟的生态系统,拥有庞大的开发者社区和持续的技术创新。Java 8引入了Lambda表达式,进一步简化了并发编程和函数式编程的实现。Java 9及以后的版本继续在模块化、性能和安全性方面进行改进,确保Java语言能够适应不断变化的技术需求和市场趋势。 MySQL是一个关系型数据库管理系统(RDBMS),它基于结构化查询语言(SQL)来管理和存储数据。MySQL由瑞典MySQL AB公司开发,并于2008年被Sun Microsystems收购,随后在2010年,Oracle公司收购了Sun Microsystems,从而获得了MySQL的所有权。MySQL以其高性能、可靠性和易用性而闻名,它提供了多种特性来满足不同规模应用程序的需求。作为一个开源解决方案,MySQL拥有一个活跃的社区,不断为其发展和改进做出贡献。它的多线程功能允许同时处理多个查询,而其优化器则可以高效地执行复杂的查询操作。 随着互联网和Web应用的快速发展,MySQL已成为许多开发者和公司的首选数据库之一。它的可扩展性和灵活性使其能够处理从小规模应用到大规模企业级应用的各种需求。通过各种存储引擎,MySQL能够适应不同的数据存储和检索需求,从而为用户提供了高度的定制性和性能优化的可能性。

    精选毕设项目-体育新闻赛事数据.zip

    精选毕设项目-体育新闻赛事数据

    chromedriver-linux64_122.0.6254.0.zip

    chromedriver-linux64_122.0.6254.0

    基于FPGA的硬件电子琴设计(文档+程序)

    基于FPGA的硬件电子琴设计(文档+程序)

    法院综合安全监管平台解决方案PPT(53页).pptx

    在科技与司法的交响曲中,智慧法院应运而生,成为新时代司法服务的新篇章。它不仅仅是一个概念,更是对法院传统工作模式的一次深刻变革。智慧法院通过移动信息化技术,为法院系统注入了强大的生命力,有效缓解了案多人少的矛盾,让司法服务更加高效、便捷。 立案、调解、审判,每一个阶段都融入了科技的智慧。在立案阶段,智慧法院利用区块链技术实现可信存证,确保了电子合同的合法性和安全性,让交易双方的身份真实性、交易安全性得到了有力见证。这不仅极大地缩短了立案时间,还为后续审判工作奠定了坚实的基础。在调解阶段,多元调解服务平台借助人工智能、自然语言处理等前沿技术,实现了矛盾纠纷的快速化解。无论是矛盾类型的多元化,还是化解主体的多元化,智慧法院都能提供一站式、全方位的服务,让纠纷解决更加高效、和谐。而在审判阶段,智能立案、智能送达、智能庭审、智能判决等一系列智能化手段的应用,更是让审判活动变得更加智能化、集约化。这不仅提高了审判效率,还确保了审判质量的稳步提升。 更为引人注目的是,智慧法院还构建了一套完善的执行体系。移动执行指挥云平台的建设,让执行工作变得更加精准、高效。执行指挥中心和信息管理中心的一体化应用,实现了信息的实时传输和交换,为执行工作提供了强有力的支撑。而执行指挥车的配备,更是让执行现场通讯信号得到了有力保障,应急通讯能力得到了显著提升。这一系列创新举措的实施,不仅让执行难问题得到了有效解决,还为构建诚信社会、保障金融法治化营商环境提供了有力支撑。智慧法院的出现,让司法服务更加贴近民心,让公平正义的阳光更加温暖人心。

    线上辅导班系统(代码+数据库+LW)

    摘  要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本线上辅导班系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此线上辅导班系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线选择试题并完成答题,在线查看考核分数。管理员管理字典管理、论坛管理、公开课管理、课程管理、课程报名管理、课程收藏管理、课程留言管理、师资力量管理、用户管理、管理员管理等功能。线上辅导班系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:线上辅导班系统;SSM框架;Mysql;自动化

Global site tag (gtag.js) - Google Analytics