突突英雄

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

       在说动态编译之前先说说静态编译,静态编译就是你在编译程序生成.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();
        }

 

 

 

  

 

posted on 2019-04-08 22:21  突突英雄  阅读(517)  评论(0编辑  收藏  举报