文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JDK6动态编译的方法是什么

2023-06-17 13:21

关注

这篇文章主要介绍“JDK6动态编译的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JDK6动态编译的方法是什么”文章能帮助大家解决问题。

JDK6开始提供了动态编译的API,在许多应用场景都可以用得着,如动态加载(修改)服务、高性动态业务逻辑实现(用脚本或模板引擎实现效率满足不了需求)等都非常好用。
API对应的接口都在javax.tools包下面,常用编译方式有基于文本文件、内存字符串等,实际上基于URI的字节流都可以,也就是远程Java源代码也可以。对于常用的已有文件形式的动态编译网上的实例已经非常多,我在这里介绍下动态编译内存中以字符串的形式。
简单的代码流程如下:

Java代码

//通过系统工具提供者获得动态编译器     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();     //获得一个文件管理器,它的功能主要是提供所有文件操作的规则,     //如源代码路径、编译的classpath,class文件目标目录等,其相关属性都提供默认值     StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);         //获得CompilationTask并调用     //获得CompilationTask方法原型:     getTask(Writer out,          JavaFileManager fileManager,          DiagnosticListener<? super JavaFileObject> diagnosticListener,          Iterable options,          Iterable classes,          Iterable<? extends JavaFileObject> compilationUnits)             //简单调用例子     boolean b = jc.getTask(null, fileManager, null, null, null, compilationUnits).call();


我这里介绍的字符串形式的编译(其它方式也会有相似的具体实现),还需要提供一个FileObject一个实现类,将相应的对象封装作为getTask()的最后一个参数来构建具体的编译Task.
JavaDoc提供的一个FileObject参考实现:
Class JavaSourceFromString

Java代码

import java.net.URI;         import javax.tools.SimpleJavaFileObject;         public class JavaSourceFromString extends SimpleJavaFileObject {                     final String code;                     JavaSourceFromString(String name, String code) {             super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),                   Kind.SOURCE);             this.code = code;         }             @Override        public CharSequence getCharContent(boolean ignoreEncodingErrors) {             return code;         }     }
 


完整的测试类:
Class TestDyCompile

Java代码

import java.io.File;     import java.io.IOException;     import java.util.Arrays;         import javax.tools.JavaCompiler;     import javax.tools.JavaFileManager.Location;     import javax.tools.JavaFileObject;     import javax.tools.StandardJavaFileManager;     import javax.tools.StandardLocation;     import javax.tools.ToolProvider;         import dyclass.Test;             public class TestDyCompile {                     public static void main(String[] args) {                          StringBuilder classStr = new StringBuilder("package dyclass;public class Foo implements Test{");             classStr.append("public void test(){");             classStr.append("System.out.println(\"Foo2\");}}");                          JavaCompiler jc = ToolProvider.getSystemJavaCompiler();             StandardJavaFileManager fileManager = jc.getStandardFileManager(null, null, null);             Location location = StandardLocation.CLASS_OUTPUT;             File[] outputs = new File[]{new File("bin/")};             try {                 fileManager.setLocation(location, Arrays.asList(outputs));             } catch (IOException e) {                 e.printStackTrace();             }                          JavaFileObject jfo = new JavaSourceFromString("dyclass.Foo", classStr.toString());             JavaFileObject[] jfos = new JavaFileObject[]{jfo};             Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(jfos);             boolean b = jc.getTask(null, fileManager, null, null, null, compilationUnits).call();             if(b){//如果编译成功                 try {                     Test t = (Test) Class.forName("dyclass.Foo").newInstance();                     t.test();                 } catch (InstantiationException e) {                     e.printStackTrace();                 } catch (IllegalAccessException e) {                     e.printStackTrace();                 } catch (ClassNotFoundException e) {                     e.printStackTrace();                 }             }         }     }


我在这里的具体业务类为dyclass.Foo,也就是我们需要动态编译的类,为了方便写业务的调用代码,也可以让我们的业务类实现一个接口,然后通过反射获得具体子类强制转换来调用。
Test接口:

Java代码

public interface Test {         //业务方法签名         void test();     }


另外,在代码中还有这么一段:

Java代码

  Location location = StandardLocation.CLASS_OUTPUT;              File[] outputs = new File[]{new File("bin/")};     try {         fileManager.setLocation(location, Arrays.asList(outputs));     } catch (IOException e) {         e.printStackTrace();     }

这段代码的作用相信大家一看到它就想到它的作用了,前面有说过JavaFileManager 的作用,我在这里设置了CLASS文件的输出目录,意图很简单,我的工程是在Eclipse运行的,项目的目标路径就是项目下的bin目录,如果不设置的话,class文件输出路径即为默认值,也就是直接在项目根路径下,后面直接调用就不能完成了。当然在其它一些应用场景中需要设置为自己需要的目录。
同样的方法可以设置JavaFileManager 其它的我们需要的文件规则属性(可以参照枚举类型StandardLocation),在这里就不一一介绍了。

关于“JDK6动态编译的方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯