Java动态编译
来源:互联网 发布:mac虚拟机内存分配 编辑:程序博客网 时间:2024/05/16 17:52
动态编译一直是Java的梦想,从Java1.6开始支持动态编译,可以在运行期直接编译.java文件,执行.class,并且能够获取相关的输入输出,甚至还能监听相关事件。
给出一个简单的动态编译例子:
动态编译虽然很好,但是我们要注意以下几点:
1,在框架中谨慎使用
比如在Struts中使用动态编译,动态实现一个类,它若继承ActionSupport就希望它成为一个Action。能做到,但是Debug很困难;在比如在Sping中,写一个动态类,要让他动态注入到Spring容器中,这是需要花费老大功夫的。
2,不要在高性能的项目中使用
动态编译毕竟需要一个编译过程,与静态编译比多了一个执行环节,因此在高性能项目中不要使用动态编译。不过,如果是在工具类项目中它则可以很好的发挥其优越性,比如在Eclipse工具中写一个插件,就可以很好的使用动态编译,不用重启就可以实现运行,调试功能,非常方便。
3,动态编译要考虑安全问题
如果你在WEB界面上提供一个功能,允许上传一个Java文件然后运行,这是典型的注入漏洞,只要上传一个恶意的Java程序,就可以让你所有的安全工作毁于一旦 。
4,记录动态编译过程
建议记录源文件,目标文件,编译过程,执行过程等日志,不仅仅是为了诊断,还是为了安全和审计,对Java项目来说,空中编译和运行时很不让人放心的,留下这些依据可以更好的优化程序。
给出一个简单的动态编译例子:
DynamicCompilation.javapackage org.xxz.test;import java.io.IOException;import java.lang.reflect.Method;import java.net.URI;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import javax.tools.JavaCompiler;import javax.tools.JavaFileObject;import javax.tools.SimpleJavaFileObject;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;public class DynamicCompilation { public static void main(String[] args) throws Exception { // java源代码 String sourceStr = "public class Hello{" + // "public String sayHello(String name){return \"Hello,\" + name + \"!\";}" + // "}"; // 类名以及文件名 String clsName = "Hello"; // 方法名 String methodName = "sayHello"; // 当前编译器 手动的将jdk/lib/tool.jar 复制到 jre/lib/目录下,不然会有空指针异常 JavaCompiler cmp = ToolProvider.getSystemJavaCompiler(); // Java标准文件管理器 StandardJavaFileManager fm = cmp.getStandardFileManager(null, null, null); // Java文件对象 JavaFileObject jfo = new StringJavaObject(clsName, sourceStr); // 编译参数,类似于javac <options>中的options List<String> optionsList = new ArrayList<String>(); // 编译文件的存放地方,注意:此处是为Eclipse工具特设的 optionsList.addAll(Arrays.asList("-d", "./bin")); // 要编译的单元 List<JavaFileObject> jfos = Arrays.asList(jfo); // 设置编译环境 JavaCompiler.CompilationTask task = cmp.getTask(null, fm, null, optionsList, null, jfos); // 编译成功 if (task.call()) { Object obj = Class.forName(clsName).newInstance(); Class<? extends Object> cls = obj.getClass(); // 调用sayHello方法 Method method = cls.getMethod(methodName, String.class); String str = (String) method.invoke(obj, "Dynamic Compilation"); System.out.println(str); } }}class StringJavaObject extends SimpleJavaFileObject { private String content = ""; // 遵循Java规范的类名及文件 public StringJavaObject(String _javaFileName, String _content) { super(_createStringJavaObjectUri(_javaFileName), Kind.SOURCE); content = _content; } // 产生一个URL资源路径 private static URI _createStringJavaObjectUri(String name) { return URI.create("String:///" + name + Kind.SOURCE.extension); } // 文本文件代码 @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return content; }}
动态编译虽然很好,但是我们要注意以下几点:
1,在框架中谨慎使用
比如在Struts中使用动态编译,动态实现一个类,它若继承ActionSupport就希望它成为一个Action。能做到,但是Debug很困难;在比如在Sping中,写一个动态类,要让他动态注入到Spring容器中,这是需要花费老大功夫的。
2,不要在高性能的项目中使用
动态编译毕竟需要一个编译过程,与静态编译比多了一个执行环节,因此在高性能项目中不要使用动态编译。不过,如果是在工具类项目中它则可以很好的发挥其优越性,比如在Eclipse工具中写一个插件,就可以很好的使用动态编译,不用重启就可以实现运行,调试功能,非常方便。
3,动态编译要考虑安全问题
如果你在WEB界面上提供一个功能,允许上传一个Java文件然后运行,这是典型的注入漏洞,只要上传一个恶意的Java程序,就可以让你所有的安全工作毁于一旦 。
4,记录动态编译过程
建议记录源文件,目标文件,编译过程,执行过程等日志,不仅仅是为了诊断,还是为了安全和审计,对Java项目来说,空中编译和运行时很不让人放心的,留下这些依据可以更好的优化程序。
- java 内存编译-动态编译
- 动态编译JAVA程序
- 动态编译Java程序
- 动态编译JAVA程序
- JAVA动态编译简介
- 动态编译JAVA程序
- 动态编译JAVA程序
- Java动态编译
- Java的动态编译
- Java动态编译
- JAVA 的动态编译
- Java动态编译
- Java动态编译
- JAVA动态编译
- java动态编译
- Java动态编译笔记
- Java动态编译(一)
- 动态编译Java源文件
- Codeforces Round #131 (Div. 2) / 214A System of Equations(枚举&优化)
- 设备模型之一 kobject & kset
- Oracle名称含义列表
- 美女薄情馆7.0.0破解VIP
- Linux2.6内核 -- 结构的初始化
- Java动态编译
- 设备模型之二 总线设备驱动
- HDOJ 4280 - Island Transport 裸最大流(Dinic) ..申请更多栈空间...
- ORACLE 中ROWNUM用法总结!
- Java调用脚本语言(JavaScript)
- 每天一个OpenGL程序 第五篇 四边形的绘制
- linux 命令行和图型界面的切换vi中保存退出常用的命令
- Android中资源文件夹res/raw和assets的使用
- 让cocos2d-x的第一个程序在android上跑起来