开心一笑
【年底是各种案件的高发期,我们去ATM取钱的时候,一定要注意遮挡,不要被陌生人看到你的余额,要不然啊,就,,,非常容易被人嘲笑。其实对于胖子来说,买衣服最简单了,都不用进去。直接就在门口问一句:“老板,有我能穿的衣服么”? 老板瞅了我一眼:“没有”! 那我就毫不犹豫的走到下一家。反正在胖子的眼里,衣服没有好看不好看,只有能穿和不能穿! 】
提出问题
java中的动态编译和静态编译如何理解???
解决问题
1.概念
静态编译:一次性编译。在编译的时候把你所有的模块都编译进去。
动态编译:按需编译。程序在运行的时候,用到那个模块就编译哪个模块。
2.实例
例一:
/**
* @Author 阿毅
* Created by Ay on 2016/01/05.
*/
class Ay{
public static void main(String[] args) {
//如编译后的Boy.class文件消失,会报错误:java.lang.NoClassDefFoundError
Boy boy = new Boy();
boy.sayHello();
}
}
class Boy implements Person{
public void sayHello(){
System.out.println("say hello .....");
}
}
interface Person{
void sayHello();
}
例二:
比如开发一个阅读器,支持txt,pdf,doc三种格式。我们把读txt,读pdf,读doc定义为三个功能模块。
静态编译:我想看个txt,点击应用程序图标以后,三个功能都加载进来了。在这里,另外两个模块的作用就是占用系统资源。
动态编译:我想看个txt,点击应用程序,判断格式,只加载读txt模块,使用读txt模块。。。
显然,动态编译1速度快,2节省了系统资源,3利于今后拓展。。。。。。。。
例三:
把下面的例子拷贝到上面的main方法中:
/**
* @Author 阿毅
* Created by Ay on 2016/01/05.
*/
public class Ay{
public static void main(String[] args) {
System.out.println("请输入您要输入的类的名字");
//输入一个类的名字
java.util.Scanner sc = new java.util.Scanner(System.in);
String s = sc.next();
//加载这个类
Class c = Class.forName(s);
//获得这个类的实例化对象
Object obj = c.newInstance();
//强制转型
Person person = (Person)obj;
person.sayHello();
}
}
我们把编译文件Boy.class删除,上面代码编译并未报错。但是运行时候会出现NoClassDefFoundError异常,这时候我们用把删除掉的Boy.class重新放回原处,重新运行,这时候,代码就可以正常运行。
这样我们可以在不停止程序运行的情况下,动态地加载一个类。我认为这体现出了Java的动态性。通过上面的例子,我认为java语言是一种“半动态”性的语言。
3.最简单的动态编译例子
/**
* @Author 阿毅
* Created by Ay on 2016/01/05.
*/
public class Ay{
public static void main(String[] args) throws Exception{
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int flag = compiler.run(null, null, null,"D:\\HelloWorld.java");
System.out.println(flag == 0 ? "编译成功" : "编译失败");
}
}
/**
* D盘放置的类的内容
* Created by HuangWenYi on 2017/1/6.
*/
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
解释一下:
第一个参数:为java编译器提供参数
第二个参数:得到java编译器的输出信息
第三个参数:接受编译器的错误信息
第四个参数:可变参数(是一个String数组)能传入一个或多个java源文件
返回值:0表示编译成功,非0表示编译失败
4.动态运行编译好的类
/**
* @Author 阿毅
* Created by Ay on 2016/01/05.
*/
public class Ay{
public static void main(String[] args) throws Exception{
//获得系统的java编译器
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//编译文件,编译成功返回 0 否则 返回 1
int flag = compiler.run(null, null, null,"D:\\HelloWorld.java");
System.out.println(flag == 0 ? "编译成功" : "编译失败");
//指定class路径,默认和源代码路径一致,加载class
URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file:/d:/")});
Object printer = classLoader.loadClass("HelloWorld").newInstance();
System.out.println(printer.toString());
}
}
运行结果
编译成功
HelloWorld@4c583ecf
5.慎用动态编译
- 在框架中谨慎使用
- 不要在要求高性能的项目使用
动态编译毕竟需要一个编译过程,与静态编译相比多了一个执行环节,因此在高性能项目中不要使用动态编译。 - 动态编译要考虑安全问题
它是非常典型的注入漏洞,只要上传一个恶意Java程序就可以让你所有的安全工作毁于一旦。 - 记录动态编译过程
建议记录源文件、目标文件、编译过程、执行过程等日志,不仅仅是为了诊断,还是为了安全和审计,对Java项目来说,空中编译和运行是很不让人放心的,留下这些依据可以更好地优化程序。
读书感悟
来自电影《长城》
- 人类和怪物的贪婪是没有区别的。
- 你以后会证明你的勇敢。
- 我苦练一生,只为此一战。
经典故事
【哈佛一调查报告说,人生平均只有7次决定人生走向的机会,两次机会间相隔约7年,大概25岁后开始出现,75岁以后就不会有什么机会了。这50年里的7次机会,第一次不易抓到,因为太年轻;最后一次也不用抓,因为太老。这样只剩5次,这里面又有两次会不小心错过,所以实际上只有3次机会了。】
参考文章
【1】Java中的动态和静态编译
【2】动态编译和静态编译及Java执行
【3】动态生成java、动态编译、动态加载
【4】java笔记十一:动态编译
【5】Java学习之-动态编译-DynamicCompile_反射调用
【6】Java动态编译
【7】编写高质量代码:改善Java程序的151个建议
其他
如果有带给你一丝丝小快乐,就让快乐继续传递下去,欢迎点赞、顶、欢迎留下宝贵的意见、多谢支持!