google closure js压缩器编译为本地码可执行文件的尝试

最近 @定球呀球 抱怨说 google closure 作为 java 命令行应用启动速度暴慢,什么都不做运行一次也要 1s 多,有大量 js 文件要处理时为每个文件都运行一次是要死人的。想起 gcj 作为 gcc 的 java 前端是可以将 java 代码编译为本地码执行的,于是好奇地尝试了一把,过程如下,较为曲折……

  1. 首先要 patch google closure 源码。由于 gcj 及其整合的 gnu classpath 基础类库实现目前只支持 java 5 的部分特征,所以先要把源码中不支持的部分绕过去。补丁见附件,下载至 google closure 源码根目录并 patch < closure-gcj.patch 即可。主要的修改点为:去除命令行解析逻辑中 gcj 不支持的 annotation 语法;从 OpenJDK 中补充了 gnu classpath 未实现的正则转义方法 Pattern.quote();去除了 gnu classpath 未实现的 Math.copySign() 方法
  2. 原来的命令行解析逻辑不能用了,只好增加一个简单的命令行启动入口类,见附件中的 NativeRunner.java,将其放置到 google closure 源码目录中的 src/com/google/javascript/jscomp/ 子目录中
  3. 在 google closure 源码目录中执行 ant 重新编译打包,拿到 build/ 子目录中的结果 compiler.jar
  4. 用如下 gcj 命令行将 compiler.jar 转换为本地码可执行文件:
gcj -findirect-dispatch --main=com.google.javascript.jscomp.NativeRunner -o closure compiler.jar -Wl,-Bsymbolic

最后编译出的可执行文件约 33MB 大,但测试后大失所望,和直接用 java -jar 启动速度相差无几,运行速度还慢了几乎 50%,估计是因为 gcj 还利用不了 gcc 4.6 新的 SSA 优化链的缘故吧,不过本来对 java 来说,稍有利用动态特性的地方 AOT 编译器就要大费周张地搞复杂的机制来兼容,很难赶上 JIT 编译生成代码的紧凑程度了。

话说回来,若你的 java 程序基本上是 java 1.4 兼容的,且没有使用太多动态特性,想在 C/C++ 程序中复用这些代码,那么 gcj 编译应该是最理想的解决方案了吧,呵呵。

猜你喜欢

转载自chaoslawful.iteye.com/blog/1603784
今日推荐