inkfish原创,请勿商业性质转载,转载请注明来源(http://blog.youkuaiyun.com/inkfish )。
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编译并计算。