• 动态编译


           在说动态编译之前先说说静态编译,静态编译就是你在编译程序生成.exe文件时编译器会将所有的模块加载进去,这样一来只要一启动文件,那么所有的模块都会被加载,小的一些程序不存在什么大的问题,但如果程序过大,这样就会让无用模块占用系统资源。而动态编译是先将你所有的模块编写成DDL(dynamic link library),DDL我们后边专门再讲,编写成DLL之后,程序在运行过程中用到哪个模块就加载哪个模块,不会加载无用的模块占用系统资源。

      DDL:指的是动态链接库,存在格式为.ddl,该文件中一般存在着一些可以供不同程序都可以使用的模块,所有动态编译的可执行性文件都带有DDL,如果没有那么这个程序就不能正常运行了。

      这里我再举一个例子,形象的来比喻一下动态编译和静态编译的区别:

      静态编译好比学校要举办一场篮球比赛,你是负责场地的,他们只告诉你去某某篮球场预定一个他们常用的场地,你到达了篮球场但是发现有三个场地,这个时候你也不知道他们常用的哪个,所以你就全部占了下来,然而他们真正使用的时候也是只是用一个场地,这样就导致了资源的浪费,那么动态编译就是说,你们要A场地我就占A场地,要B就占B,这样就不会影响其他场地的正常使用了。

      动态编译

      动态编译的两种做法:

      (1)、通过Runtime调用Javac,启动新的进程去操作

          Runtime run=Runtime.getRuntime();

          Process process=run.exec("javac -cp d:/myjava/ HelloWorld.java");

      (2)、通过JavaCompiler动态编译

      这里我使用第二种编译。

      代码如下:

    public static int compileFile(String sourceFile) {
            JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();
            int result=compiler.run(null,null,null,sourceFile);
            System.out.println(result==0?"编译成功":"编译失败");
            return result;
        }

      第一个参数:为Java编译器提供一个参数,是InputStream,如果为null则默认是控制台输入system.in 

      第二个参数:是OutputStream,可以获得编译器的输出信息,如果为null则默认是控制台输出system.out 

      第三个参数:也是一个输出流,接受编译器输出的一些错误信息,如果为null则默认是把错误消息输出在控制台上 system.error 

      第四个参数:可以传递多个Java源文件地址。

      返回值:0表示成功,其他数表示失败

      第一次使用时报错为空指针异常,检查了一遍代码发现并没有错误,百度之后找到了问题所在:

      ToolProvider用到的是jdk里的tool.jar包,而jre里没有这个jar文件,而我使用的就是jre,所以报了空指针异常,将jre换成jdk后问题便得到了解决,通过这个问题我也明白了jdk是开发用的,jre是运行用的,并且jre里的东西没有jdk全,所以用jdk更好

      动态运行

      通过Runtime.getRuntime()运行启动新的进程运行

      

    public class DynamicComplier {
        public static void main(String[] args)  {
            JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();
            int result=compiler.run(null, null, null,"E:/MyJava/Myjava.java");
            System.out.println(result==0?"编译成功":"编译失败");
            
            Runtime run=Runtime.getRuntime();
            
                Process process;
                try {
                    process = run.exec("java -cp E:/MyJava Myjava");
                    InputStream in=process.getInputStream();
                    BufferedReader reader=new BufferedReader(new InputStreamReader(in));
                    String str="";
                    while((str=reader.readLine())!=null) {
                        System.out.println(str);
                    }
                } catch (IOException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
        
    
            
        }
    
    }

      通过反射运行编译好的类

     

    try {
                URL[] urls=new URL[] {new URL("file:/"+"e:/myJava/")};
                URLClassLoader loader=new URLClassLoader(urls);
                Class c=loader.loadClass("Myjava");
                //调用加载类的main方法
                Method m=(Method) c.getMethod("main", String[].class).invoke(null,(Object)new String[] {"aa","bb"});
                //可变参数是JDK5.0之后才有的,上述代码会编写成m.invoke(null,"aa","bb"),
                //这样一来就与Main函数发生了参数不匹配的问题。
            }catch (Exception e) {
                e.printStackTrace();
            }

      

  • 相关阅读:
    安卓第一夜 第一个应用
    为什么要学习Linux
    Android的历史与花边
    来玩Play框架07 静态文件
    来玩Play框架06 用户验证
    来玩Play框架05 数据库
    来玩Play框架04 表单
    来玩Play框架03 模板
    来玩Play框架02 响应
    来玩Play框架01 简介
  • 原文地址:https://www.cnblogs.com/tutuhome/p/10673945.html
Copyright © 2020-2023  润新知