JAVA之動態編譯

經過Java動態生成class文件

今天說下JAVA中的動態編譯,這個功能根據我如今的瞭解好像沒有見到過用的,我Jio的吧,如今的一些在線代碼編緝器能夠用到了,這個具體我也不是很清楚。感興趣的你們能夠自已瞭解下。html

說到動態編緝你們可能會想到,動態編緝確定不是像咱們平時運行程序似的在本地的平臺就開始編譯了。java

動態編譯實際上是在程序的運行過程當中對Java文件的編譯或者是運行.class的文件。好比說我今天想裝一波,我寫個java的程序,又寫了個另外一個java的程序在小夥伴面秀,我只運行一個java程序能夠編譯另外一個java而且運行它。編程

咱們先來了解下,在JAVA的6.0版本java開始引入的動態編譯這個功能。其實在java6.0之前java也可使用動態編譯,那個時候好像是用的RunTime來實現的,感興趣的能夠了解下數組

咱們先來講下6.0之後是如何進行動坊編譯的呢?編程語言

這個時候JAVA引入了JavaCompiler,這個類主要是在程序中調用JAVA編程語言的接口,這個類是沒有構造函數的,是接收的ToolsProvider類下的靜態函數 getSystemJavaCompiler(),這個函數的主要功能得到此平臺提供的Java編程語言編譯器。 ide

下面咱們看下代碼是如何編寫的:函數

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if(compiler == null){
       System.out.println("沒有獲得初始化");
       return;
}
int restuld =  compiler.run(null,null,null,"D:/myjava/HelloWorld.java");
System.out.println(restuld == 0 ? "編譯成功":"編譯失敗");

這裏我來講下這裏是什麼意思,第一行代碼是得到JAVA的編程語言的編譯器,第二行是一個判空處理,這裏行記得加上,小編在這裏遇到了問題卡了10多分鐘,我也不知道怎麼回事系統沒有獲取到java語言的編譯器,一直 報出空指針異常的問題,我尋找了很久最後加了個判空處理髮現這裏是空的,後來我也沒有處理多運行了幾回就行了,若是有朋友發現這裏是怎麼回事評論下的,第6行代碼你們能夠理解爲是在進行編譯java源碼程序。這裏有4個參數分別是:工具

  • 爲java編譯器提供參數
  • 獲得java編譯的輸出信息
  • 接收編譯的錯誤
  • 可變參數能傳入一個或多個java源碼

  

這裏的返回值是若是編譯成功返回的是0,編譯失敗返回非0.url

你們能夠看下面這張API的截圖,能夠了解下,命令行

通過程序的運行,我成功的獲得了一個HelloWorld.class文件,到這裏你們先練習下上面的代碼,下面部分是關於如何經過反射來執行編譯生成的類。

 

經過反射來運行生成的Class類

講到這裏咱們先來了解下URLClassLoader,這個是類加載器,在咱們是用類加載器的時候構造參數是能夠傳入一個url數組,

咱們須要講類文件的url放到一個Url數組中,能夠經過建立url數組包裹url的方式來建立一個url數組,例:

URL[] urls = new URL[]{new URL("file:/" + "D:/myjava/")};

 這裏new Url的時候不瞭解的小夥伴能夠看下JAVA的API文檔url有一個構造參數是傳入的一個路徑,這個路徑是要帶上協議的,好比我要加載文件我就要帶上file協議,若是找不到協議可能會發生格式錯誤的異常。

這裏的url參數是能夠填寫目錄的,接下來咱們要構造一個類加載器(URLClassLoader)能夠經過這個類加載器加載咱們上面生成的類。

URLClassLoader loader = new URLClassLoader(urls);

使用默認委託父級ClassLoader爲指定的URL構造一個新的ClassLoader 。 在首次搜索父類加載器後,將按照爲類和資源指定的順序搜索URL。 任何以「/」結尾的URL都假定是指一個目錄。 不然,URL被認爲是指根據須要下載並打開的JAR文件。 接下來咱們要開始加載生成的類文件了:

Class c = loader.loadClass("HelloWorld");

 看到這裏相比你們應該很熟悉了吧,這裏和我上次給你們說的反射相似,這裏拿到了一個class的對象,咱們能夠經過class的對象查找方法,

Method method = c.getMethod("main",String[].class);

我這裏就和你們大概的說下由於我在反射的那篇博客和你們說了,這裏就不詳細的講解了,這裏填的兩個參數的意思是,參數一:是咱們要查找的方法名,參數二:是方法的參數類型,在main方法的參數列表裏都會有一個String數組類型的參數,主要是接受在命令行工具下填寫的參數的。經過這行命令咱們拿到了一個方法。接下來開始經過invoke方法你能夠理解成調用這個方法:

method.invoke(null,(Object)new String[]{});

這裏咱們在反射那講說要填寫一個對象,這裏咱們填寫空就能夠了,由於在java的main方法是靜態的,因此能夠直接調用,

這樣就能夠運行一個類啦,

 

不上反射的教程,傳送門

相關文章
相關標籤/搜索