Java之动态编译,静态编译简单理解和实例

开心一笑

【年底是各种案件的高发期,我们去ATM取钱的时候,一定要注意遮挡,不要被陌生人看到你的余额,要不然啊,就,,,非常容易被人嘲笑。其实对于胖子来说,买衣服最简单了,都不用进去。直接就在门口问一句:“老板,有我能穿的衣服么”? 老板瞅了我一眼:“没有”! 那我就毫不犹豫的走到下一家。反正在胖子的眼里,衣服没有好看不好看,只有能穿和不能穿! 】

Java之动态编译,静态编译简单理解和实例_第1张图片
唯美图片.png

提出问题

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个建议

Java之动态编译,静态编译简单理解和实例_第2张图片
唯美图片.png

其他

如果有带给你一丝丝小快乐,就让快乐继续传递下去,欢迎点赞、顶、欢迎留下宝贵的意见、多谢支持!

你可能感兴趣的:(Java之动态编译,静态编译简单理解和实例)