kan-java, 一個能裁剪語法特性的java動態編譯工具

'kan-java' 就是 '砍-java'

這是一個java代碼動態編譯工具,也就是可以把String形式的java代碼實時地編譯爲字節碼的工具;java

「動態編譯」工具,其實自jdk1.6發佈以來,應該出現過不少,不過kan-java的特色在於 —— 就像它的名字同樣 —— 能夠選擇性地砍掉任意語言特性;git

也就是說 —— 這是一個能夠在動態編譯java代碼的同時,對java語言語法作裁剪的動態編譯工具。程序員

經過下面這個例子能夠看出「裁剪」指的是什麼意思:github

// 禁止帶標籤的continue語句
void testLabeledContinue(){
    def kan = new KanJava(Feature.labeledContinue)
    def srcs = []
    srcs << new JavaSourceFile("TestLabeledContinue.java", "kanjava.test", readContent("testLabeledContinue/TestLabeledContinue.src"));
    def rst = kan.checkAndCompile(srcs)

    assertTrue !rst.isSuccess()
    assertTrue rst.errMsg != null
    assertTrue rst.classes == null
    println rst.errMsg
}

上述groovy代碼建立了一個KanJava編譯工具實例, 並指明想要砍掉labeledContinue特性(即帶標籤的continue語句)
其中readContent方法的返回結果以下:編程

package kanjava.test;

public class TestLabeledContinue {

    public static void main(String... args) {
        for(int i=0;i<10;i++){
            if(i == 5) continue;
        }
        label: while(true){
            if(true) continue label;
        }
    }
}

上述代碼包含2個continue語句:第一個不帶標籤而第二個帶標籤
最終輸出結果以下:api

Error at row: 10, col: 22, reason: Continue statements with labels are not allowed.

即「帶標籤的continue語句」已被禁止了,在編譯過程當中發現這種語句即會報錯, 其核心功能,概念上講就是這麼簡單。oracle

這能有什麼用?

擁有一個裁剪版本的java,這有怎樣的應用場景?框架

目前最直接的答案是"高性能的內部DSL"jvm

即當我須要一個語法上很是接近普經過程式編程語言的DSL,但卻又不想或以爲不必本身從頭實現一個(外部DSL)的時候,就能夠考慮以某種現成的過程式通用編程語言爲藍本,經過裁剪其語法達到目的;
而當這種「現成的過程式通用編程語言」被選擇爲java時,kan-java出場的時刻就到了, 試想一下,下面這樣「砍」會砍出來什麼效果? ——maven

private static final KanJava kanJava = new KanJava(Feature.assertion, 
                                                   Feature.doWhileLoop,
                                                   Feature.forLoop,
                                                   Feature.labeledBreak,
                                                   Feature.labeledContinue,
                                                   Feature.nestedClass,
                                                   Feature.whileLoop);

相信全部java程序員均可以猜到:你將獲得一個「沒有assert語句、沒有do-while循環、沒有for循環、沒有帶標籤的break、沒有帶標籤的continue、沒有嵌套類、沒有while循環」的 —— java.
P.S. 若是你還堅信它是java的話 :)

而這些"內部DSL"最終將被編譯成字節碼運行,所以也有了高速運行的基礎;
因此說kan-java可以成爲「利用java實現高性能的內部DSL」的強大工具。

上面示例中的這種「砍」法並不誇張,這是從現實中的使用案例中截選出來的。

一些更實用 & 更高級的功能

kan-java提供的api可以將「砍語法」和「編譯爲字節碼」拆分爲兩個步驟;
這使得你能夠 —— 好比說 —— 在用戶輸入的時候禁掉'import語句',而實際編譯的時候能夠正常插入import語句後再編譯, 相信這種功能會頗有用;

更廣泛意義地講,kan-java實際上提供了一套"java語言語法靜態處理框架", 在此框架之上,「砍」語法其實只是冰山一角 —— 由於你還能夠用它來「砍用法」,好比你並不想徹底禁掉import語句,但但願禁止import一些特定的類;
再好比你不想徹底禁止用戶new對象,但你可以作到不讓用戶new特定的對象...

凡是可以出如今代碼當中的任意結構,均可以被控制。
所以能夠說,被髮布出來的kan-java庫只是一個小小的核心,其更加廣闊的應用場景還有待猿們繼續擴充...

有沒有更加「高級(黑)」的話題? 固然有;由於在kan-java提供的這套框架之上不只限於能「砍」,它還能「加」...
不過目前這個庫的主要目的仍是提供一套「基於java的內部DSL構建工具」,其它的什麼「用kan-java作源碼加強」,什麼「用kan-java把java編譯到GPU上」這些黑科技就暫不展開了 :)

注意事項

最重要的事情老是最後才說...

目前kan-java所支持的java基礎語法是1.6的,也就是說,你使用kan-java來「砍」語法的時候,是以java 1.6爲基礎來砍的
不過這並不影響kan-java庫被放到更高版本的java環境中使用(above v1.6), 起碼大多數狀況下是ok的;不過,若是真的遇到問題,仍是最好能從源碼編譯一份對應當前java版本環境的kan-java庫(由於kan-java在實現上使用了com.sun包下的一些類, 這些類並不徹底保證在不一樣版本java之間的兼容)

一樣由於kan-java使用了com.sun包下的類,我也只能假定kan-java只能在oracle hotspot jvm上運行

目前開放的可被「砍」的功能,只是源於目前我我的在實際項目中的須要而已;確定還有更多可能的「花式砍法」,若是但願有,能夠提出來,有興趣的咱們能夠共建

使用kan-java時,需確保tools.jar也在classpath中

按道理講,除了java標準庫,kan-java是不須要依賴任何第三方庫的,不過項目中出現了對groovy-all的依賴,這僅僅是由於我想實踐一把"java和groovy混編開發模式"的任性而已,不要太在乎 :)

目前的發佈版本爲v0.1, maven依賴爲:

<dependency>
    <groupId>com.github.pfmiles</groupId>
    <artifactId>kan-java</artifactId>
    <version>0.1</version>
</dependency>

原文連接:https://github.com/pfmiles/kan-java

相關文章
相關標籤/搜索