利用javax.tools動態編譯執行java程式碼
javax.tools 包是一種新增到 Java SE 6 的標準 API,可以實現 Java 原始碼編譯,使您能夠新增動態功能來擴充套件靜態應用程式。本文將探查javax.tools包中提供的主要類,以Java表示式表示計算一個數值函式y=x*x+x。更多詳情請參考《使用 javax.tools 建立動態應用程式》和javax.tools API docs 。
complier.CharSequenceCompiler原始碼:
complier.CharSequenceCompilerException原始碼:
complier.ClassLoaderImpl原始碼:
complier.FileManagerImpl原始碼:
complier.JavaFileObjectImpl原始碼:
complier.Utils原始碼:
以上程式碼為complier包中所有類,它對外暴露的主要方法是:CharSequenceCompiler<T>.compile(String qualifiedClassName, CharSequence javaSource, Class<?>... types) throws CharSequenceCompilerException, ClassCastException,通過它來動態編譯字串形式表示的java原始碼。除此之外,包中其他方類和方法儘量使用預設訪問許可權,以避免他人誤用以及隱藏實現細節。
下面是測試package中的內容:
complier.test.Function原始碼:定義了一個介面,動態編譯的所有類實現這個介面。
complier.test.Function實現類的模板,方便類的生成。
complier.test.ExpressionCal原始碼:裡面含有一個靜態測試類ExpressionCal$Tester。
ExpressionCal$Tester測試表達式x*x+x的執行,具體測試直接計算、java編譯並計算、javascript編譯並計算的效率,共測試三遍以觀察其效率的變化,每一遍中每種方法又用for迴圈執行10萬次計算,忽略列印輸出的耗時。測試時間使用微秒為單位,精確度取決於System.nanoTime(),詳見其java docs中的說明。測試結果如下:
整理得到:
10萬次計算 (單位:毫秒) |
直接計算 | java編譯並計算 | JS編譯並計算 | ||
編譯 | 計算 | 編譯 | 計算 | ||
第一遍 | 6.46 | 604.57 | 5.41 | 23.35 | 8671.08 |
第二遍 | 0.67 | 44.71 | 1.4 | 2.38 | 8493.12 |
第三遍 | 0.57 | 39.49 | 1.38 | 1.87 | 8624.12 |
可以看出,java直接計算速度超快,java編譯並計算速度還是比直接計算慢1倍(不計編譯時間),而JS的計算速度比直接計算慢4個數量級,簡直慘不忍睹。第一次執行除JS計算外,均比較耗時,其中java第一次編譯需要從磁碟上讀取template檔案,以後則均為記憶體操作。
從測試結果看,如果需要執行一個固定的表示式,可以寫死在Java程式中(廢話),如果需要計算一個動態變化的表示式,如果計算次數較少(500次以下),JS較為划算,如果計算次數十分巨大,則需要考慮java編譯並計算。