java 动态编译&load

有时候我们需要把一些外部资源(比如第三方jar,自己动态生成的java文件)编译并加载到classloader,这时我们就需要JavaCompiler 个类,jdk是从1.6开始支持此功能
网上有很多类似列子,搜索“动态编译”可以找到,我这里只列出一种实现方法(按原理分好像有三种可参考:http://www.cnblogs.com/flyoung2008/archive/2011/11/14/2249017.html

public class TestClient {

    public static void main(String[] args) throws Exception {
        String c ="package webservice;\n"+
                "public class Hello{\n" +
                "\n" +
                "    public static void main(String[] args) {\n" +
                "        System.out.println(\"初始化成功了!\");\n" +
                "    }\n" +
                "}\n";
        /**
         * 先把文件写入磁盘
         */
        String src = "/src";
        String bin = "/bin";
        File srcdir = new File(System.getProperty("user.dir") + src+"/webservice"); //java目录
        File classdir = new File(System.getProperty("user.dir") + bin+"/webservice"); //.class目录
        // 如果 \temp 不存在 就创建
        if (!srcdir.exists()) {
            srcdir.mkdir();
        }
        FileWriter writer = new FileWriter(new File(srcdir,"Hello.java"));
        writer.write(c);
        writer.flush();
        writer.close();
        /**
         * 从磁盘中加载类并编译
         */
        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager(null, null, null);
        Iterable it = javaFileManager.getJavaFileObjects(new File(srcdir,"Hello.java"));
        JavaCompiler.CompilationTask task = javaCompiler.getTask(null, javaFileManager, null, null, null, it);
        Boolean call = task.call();
        javaFileManager.close();
        System.out.println(call);

        /**
         * 生成URLClassLoader  加载.class文件
         *路径为.class文件的上级目录
         * 生成的.classs文件包名要与loadClass(className)中className一致
         * url前面要加上file://,不能直接写文件路径
         */
        URL url[] = new URL[]{new URL("file://D:/user/828470/workspace2/TestForJava/src")};
        URLClassLoader loader = new URLClassLoader(url);
        loader.loadClass("webservice.Hello").getDeclaredMethod("main",String[].class).invoke(null,new String[]{null});

        Class.forName("webservice.Hello").getDeclaredMethod("main",String[].class).invoke(null,new String[]{null});

    }
   }

getTask()方法 jdk描述

JavaCompiler.CompilationTask getTask(Writer out,
                                     JavaFileManager fileManager,
                                     DiagnosticListener<? super JavaFileObject> diagnosticListener,
                                     Iterable<String> options,
                                     Iterable<String> classes,
                                     Iterable<? extends JavaFileObject> compilationUnits)

使用给定组件和参数创建编译任务的 future。该编译可能没有完成,正如 CompilationTask 接口中所述。
如果提供了文件管理器,则它必须能够处理 StandardLocation 中定义的所有位置。
参数
out - 用于来自编译器的其他输出的 Writer;如果为 null,则使用 System.err
fileManager - 文件管理器;如果为 null,则使用编译器的标准文件管理器
diagnosticListener - 诊断侦听器;如果为 null,则使用编译器的默认方法报告诊断信息
options - 编译器选项;null 表示没有选项
classes - 类名称(用于注释处理),null 表示没有类名称
compilationUnits - 要编译的编译单元;null 表示没有编译单元
返回
表示编译的对象
抛出
RuntimeException - 如果在用户提供的组件中发生不可恢复的错误。cause 为用户代码中的错误。
IllegalArgumentException - 如果给定的任一编译单元具有不同于 source 的类型

注:代码中的注释部分是特别需要注意的地方,本人由于目录没配好浪费了很多时间,

声明:借用“像少年啦飞驰“这位同学的文章,在此谢过
特此发誓:只为传承,绝无他用!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值