1. 程式人生 > >Java動態編譯

Java動態編譯

code rgs pac 工程 tool getname rri n) tac

Java動態編譯

最近熟悉了一下反射,對Java的動態性有了進一步的了解,因此想實現一下用Java直接動態生成.class文件,也就是在編譯完成後,運行時編譯java文件

工程結構

?  helloworld tree
.
├── bin
│?? └── helloworld
│??     ├── Car.java
├── src
│?? └── helloworld
│??     ├── TestDynamicCompile.java

測試程序

TestDynamicCompile.java

package helloworld;

import java.net.MalformedURLException;
import java.util.Scanner;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;


public class TestDynamicCompile {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, MalformedURLException {
        Scanner scanner = new Scanner(System.in);
        String className = "helloworld.Car";//scanner.next(); // "helloworld.Car"
        scanner.close();
        
        try {
            Class.forName(className);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            System.out.println("Class not found");
            System.out.println("dynamic compiling...");
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
             // 等同於javac 命令,生成的class文件默認在.java文件的同一個文件夾下
            int flag = compiler.run(null, null, null, "bin/helloworld/Car.java");
            System.out.println(flag==0? "編譯成功" : "編譯失敗");
        }   
        try {
                Class<?> c = Class.forName(className);
                Object obj = c.newInstance();
                System.out.println(obj);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }
}

將被動態編譯的程序

Car.java(放在bin/helloworld目錄下)

package helloworld;

public class Car {
    private String name;
    private int ID;
    @Override
    public String toString() {
        return "name = " + name + "  ID = " + ID;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getID() {
        return ID;
    }
    public void setID(int ID) {
        this.ID = ID;
    }
    public Car(){
        this.name = "Default";
        this.ID = 123;
    }
}

編譯TestDynamicCompile.java

?  helloworld tree
.
├── bin
│?? └── helloworld
│??     ├── Car.java
│??     └── TestDynamicCompile.class
├── src
│?? └── helloworld
│??     ├── TestDynamicCompile.java

可以看到Car還未被編譯,TestDynamicCompile.class已經靜態編譯完成

運行後

?  helloworld tree
.
├── bin
│?? └── helloworld
│??     ├── Car.class
│??     ├── Car.java
│??     └── TestDynamicCompile.class
├── src
│?? └── helloworld
│??     ├── TestDynamicCompile.java

可以看到Car.class字節文件在運行時被JavaCompiler編譯出來

運行輸出

Class not found
dynamic compiling...
編譯成功
name = Default  ID = 123

小結

Java實現了"自舉",可以自己編譯自己,而不用再起一個javac進程來外部編譯。感覺這種註入代碼的方式有一定的靈活性。

Java動態編譯