Chrome V8 引擎移植到 Android

简介

Chrome V8 引擎是 Google 自己开发的 javascript 脚本引擎。开发语言为 C++。

  • V8 github 页面
  • V8 官方博客
  • V8 开发者页面

在 Android 平台上的浏览器框架如下图,是基于 WebKit 实现的。其中 JS Engine 部分,在 Android 2.2 版本以前使用的是 JavaScriptEngine, 在 Android 2.2 及以后版本使用了 V8 引擎。
Chrome V8 引擎移植到 Android_第1张图片

关于 WebKit 的更多资料:

http://www.infoq.com/cn/articles/webkit-for-developers

http://blog.inching.org/2013/12/03/webkit/

在 Android 上如果要运行 JavaScript。有三种方式:

  1. 通过 WebView API 来执行 JS 代码。

    这种方式通过直接调用 Android 控件来实现,开发难度最低,限制性较大,性能较低。

    使用方法 Google 一下

  2. 通过调用系统的 V8 库来执行。

    这块我目前还没调研,可以借鉴这篇 StackOverflow 的回答

  3. 自己编译 V8 作为应用程序自带的库来调用。

    由于 V8 是开源的,可以通过自己编译 V8 引擎来使用。这样可定制性最好。

本文重点介绍如何自己编译 V8 引擎作为应用程序自带的库来调用。

编译 V8 源码

自己编译

自己尝试编译 V8 引擎,需要根据 官方提供的编译流程进行编译环境准备和工具安装。下面是官方的集成流程。也可以通过官方 github wiki 页面查看完整的最新文档。

  1. Using Git

  2. Building with Gyp

    • Using Git

      其中可以看出不是用git 命令直接 clone 或者 pull V8 的代码,是需要使用 depot_tools 中的 gclient 获取 V8 代码。

    • install gclient(depot_tools)

关于 D8 on Android 这篇文章:

我一开始看到这篇文章,以为是介绍如何把 V8 引擎移植到 Android 的干货,但是其实不是的。

D8 是 V8 引擎的命令行工具,所以 D8 on Android 这篇文章是叫你如何在 Android 命令行 「adb tool 」中集成 D8 从而支持运行 JS 脚本的。

所以要集成 V8 引擎,并不是看这篇文章。

目前自己编译 V8 源码遇到的问题:

  1. make android_arm.release 遇到错误
  2. 编译产物过大(800M),而例如 NativeScript 项目中 使用的 V8 引擎包只有几十M。

基于以上问题,目前暂时没有用自己编译的V8 引擎。

借鉴 V8Android 项目源码

V8Android 是 GitHub 上的一个开源项目,它实现了在 Android 端调用 V8 引擎的简单 DEMO。

通过这个Android 工程可以完成简单的调用 V8 引擎的实践。

不过这个工程有两个问题:

  1. 使用的 Eclipse 工程结构开发,目前要在 AndroidStudio 上使用的话需要进行相关调整。
  2. 使用的 V8引擎较久。由于 V8 引擎已经经过了多版本的迭代,API 也有较大的更改。所以如果基于这个工程的 V8引擎进行开发,后续做V8 引擎的版本更新很麻烦。

使用 NativeScript 项目源码

NativeScript 是 GitHub 上的一个开源项目,它实现了在 IOS 和 Android 上使用 JS 进行应用开发的框架。AndroidRuntime 是 NativeScript 在 Android 上实现其 JS 运行能力的一个开源项目,这个项目也是基于 V8 开发的。

由于NativeScript 的更新比较频发,他的AndroidRuntime 使用的 V8 版本也是较新的版本。所以我们可以使用 AndroidRuntime 中集成的 V8 库来进行我们的应用开发。

更极端的,可以直接基于 AndroidRuntime 项目进行你的应用开发。AndroidRuntime 提供了更加便利的面向应用层的框架。

本文采取的集成方案是使用 AndroidRuntime 中引用的V8 库和对应NDK-build 配置文件进行我的 V8 引擎的封装。后续章节会有详细介绍。

集成 V8 引擎

在上述章节说了本文采取的集成方案,是使用 AndroidRuntime中引用的 V8 引擎库和对应的 NDK-BUILD 配置文件进行我的 V8引擎的封装。

之所以这么做,是因为在 Android 中进行 C++ 库的构建,需要编写 Android.mk 和 Application.mk 两个配置文件,而 V8 引擎的编译对所依赖的一些 静态库文件,以及依赖的 Android NDK 库,还有一些编译选项有特定的要求。所以如果要编译成功,对 Android.mk 和 Application.mk 两个文件的编写有一定的难度。所以这里索性直接使用 AndoridRuntime 中的配置文件来进行集成。

具体集成步骤:

  1. 正确配置 Android NDK-BUIlD 环境。具体步骤查看Android NDK 官网

  2. 将 AndroidRuntime 「/src/jni 」目录的 Android.mk 和 Application.mk 文件拷贝到你的 「/src/jni 」目录。

  3. 将 V8 的静态库文件拷贝到「 /src/jni/libs」目录。

    Android.mk 文件中对静态库文件的路径都有配置,在做完这部的时候,注意查看 Android.mk 文件中的静态文件路径是否指向了你实际方式静态文件的位置。如果错误,会导致 ndk-build 编译失败。

  4. 将 V8 的头文件拷贝到 「 /src/jni/include」目录。

    一般直接把 Android-Runtime 项目中的 include 目录整个拷贝过来就行。你也可以在其使用的 V8 版本的源码中的 include 目录找到这些头文件。

  5. 添加你的应用的 JNI 接口头文件,并实现。这一步在下个章节重点说明。

  6. 使用 ndk-build 工具编译出 so 包。

应用层 JNI API 开发

在 Android 中必须通过 JNI 接口来使用 C++ 的库。所以如果要在 Android 中使用 V8 引擎,必须根据我们应用层需要,开发JNI 接口,并在JNI 接口的 C++ 实现中调用 V8 引擎。

具体步骤:

  1. 在 JAVA 类中声明 native 方法。
  2. 使用 javah 工具生成包含对应的 JNI 接口的头文件
  3. 将头文件移动到 /src/jni 目录下,并创建对应的cpp 文件,实现对应的接口。

下面详细介绍 JNI 接口实现。

实现 JNI 接口

在实现 JNI 的过程中,可以参考的资料:

  • Chrome V8 官方说明文档。可以通过它知道 V8 的一些特性。

  • V8 源码 Sample 目录。可以知道基本的使用

    请注意不同版本的 Sample 可能不一样。请查看自己版本对应的 git 中的 Sample 目录。

  • AndroidRuntime 中对应的实现。通过他可以了解很多 V8 API 的用法。

关于这里实现 JNI 的小提示:

  • JNIEnv 提供的API 要区分 C 和 C++,请确认清楚。

你可能感兴趣的:(JS,android)