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

相关文章
相关标签/搜索