【问题标题】:How can I detect which javascript engine (v8 or JSC) is used at runtime in Android?如何检测 Android 运行时使用的 javascript 引擎(v8 或 JSC)?
【发布时间】:2011-07-20 20:57:53
【问题描述】:

较新版本的 Android (> 2.2) 包含 v8 javascript 引擎,而较旧版本只有 JSC。但是,根据http://blogs.nitobi.com/joe/2011/01/14/android-your-js-engine-is-not-always-v8/,在运行时使用哪个 javascript 引擎似乎取决于构建时存在的环境变量 (JS_ENGINE),以及设备的硬件规格:

# The default / alternative engine depends on the device class.
# On devices with a lot of memory (e.g. Passion/Sholes), the
# default is V8. On everything else, the only choice is JSC.

我的问题是:有什么方法可以从网页、嵌入式 WebView 或应用程序中确定正在使用哪个 javascript 引擎?

如果答案是否定的,有没有人知道Android模拟器使用的是哪个JS引擎?


我问这个的原因是因为这个问题:http://code.google.com/p/android/issues/detail?id=12987

基本上,JSC 中的 javascript-to-java 桥可能在 Android 2.3.X 上被破坏,这会影响我正在尝试编写的应用程序。我在模拟器的 JNI 深处看到了一个段错误,但在我测试过的少数物理设备上却没有。我正在尝试确定这是仅限于模拟器的东西、仅限 JSC 的东西,还是完全不同的东西。

【问题讨论】:

  • 有一些api差异吗?例如:jscOnlyObject === 未定义
  • 我不知道 - 但如果有人知道,那将是完美的。

标签: javascript android v8 javascript-engine


【解决方案1】:

我认为更好的问题是:你为什么在乎?您基本上陷入了很多人在 90 年代末/00 年代初陷入的“浏览器检测”陷阱。不过,从那时起,我们了解到 特征检测 是更有用的方法,尤其是因为给定浏览器支持的特征(大部分)是移动目标。现在有代码在 IE9 上运行,其 DOM 和 JavaScript 支持得到了显着改进,但没有使用这些功能,因为它正在执行浏览器检测并依赖 IE6 技术。

因此,不必担心 V8 与 JSC,只需担心您想要的功能。我对 JSC 一无所知,但例如让我们假设它在 V8 具有的数组上没有 forEach 方法(ECMAScript 第 5 版标准的一部分)。而不是抛出一个大的“V8 vs. JSC”杠杆,你会这样做:

if (typeof Array.prototype.forEach === "function") {
    // Code that expects `forEach`
}
else {
    // Code that falls back
}

(您的“回退代码”可能添加 forEach 到原型中,或者此测试可能在您自己的迭代器函数中,您想知道是否推迟到本机实现或自己提供。)

对于您想要使用的其他可能存在也可能不存在的功能也是如此。


但是,如果您确实需要检测 V8 与 JSC(从您的评论看来您可能),this page 似乎展示了一种这样做的方法,尽管它看起来非常脆弱。这是我稍微修改过的版本(尤其是用WebkitAppearance 的测试替换window.devicePixelRatio——前者至少在其他一些浏览器上会出现误报[例如,Firefox,它使用 Gecko,而不是 WebKit]):

var v8string = 'function%20javaEnabled%28%29%20%7B%20%5Bnative%20code%5D%20%7D';

if ('WebkitAppearance' in document.documentElement.style) { //If (probably) WebKit browser
    if (escape(navigator.javaEnabled.toString()) === v8string) {
        console.log('V8 detected');
    } else {
        console.log('JSC detected');
    }
} else {
    console.log("Not a WebKit browser");
}

检测 Chrome(也使用 V8)和 Safari(也使用 JSC)之间的差异对我有用。

【讨论】:

  • 我关心这个问题:code.google.com/p/android/issues/detail?id=12987 - 基本上,可能是 JSC 中的 javascript-to-java 桥在 Android 2.3.X 上被破坏了,这会影响我正在使用的应用程序试图写。我在我的模拟器的 JNI 深处看到了一个段错误,我正在尝试确定这是一个仅限模拟器的东西,一个仅限 JSC 的东西,还是完全不同的东西。
  • @digitalbath:啊。迷人的。 (七个月,谷歌基本上没有澄清。不好。)我已经更新了答案,指出我希望有所帮助的东西。最好的,
  • 很棒的信息。我刚刚在一个允许使用 javascript 制作增强现实应用程序的框架中测试了一个非浏览器实现。我发现它以 JSC 为核心。但我完全同意我们应该追求“功能可用性”而不是 JS 引擎之间的战斗。
  • 旁注:v8String 条件也适用于 Presto 引擎。
【解决方案2】:

虽然上面的答案指出了最好的方法,但我想我会指出另一种从本地库中执行此操作的方法。

void *dlWebCoreHandle = dlopen("libwebcore.so", RTLD_NOW);
void *v8GetVersion = dlsym(dlWebCoreHandle, "_ZN2v82V810GetVersionEv");
if (v8GetVersion == NULL) {
    /* does not appear to be V8 */
} ... etc.

不幸的是,导出的符号被损坏了,因此无法 100% 保证固件制造商使用的编译器会以相同的方式损坏符号(在带有符号的库上使用 nm --defined-only libwebcore.so -g)。可以通过 JNI 公开这个函数并从 Java 代码内部检查。

libwebcore.so 库还将V8_Fatal 列为符号之一,该符号不易被修改。

JSC 将有一些其他导出的符号,您可以从本机库中检查这些符号。如果两者都不存在,您可以回退到其他方法。

【讨论】:

    【解决方案3】:

    var s = '';
    for (x in {
        3: 3,
        1: 1
      }) {
      s += x
    }
    if (s === '31') {
      alert('JSC');
    } else {
      alert('V8');
    }

    顺便说一下,这会将 Firefox 归类为“JSC”,较新的 IE 版本看起来像 V8。

    我的博文有更多 V8 嗅探技巧:http://erikcorry.blogspot.dk/2012/12/which-version-of-v8-do-i-have.html

    【讨论】:

      猜你喜欢
      • 2023-04-03
      • 2021-04-18
      • 2013-04-21
      • 2016-05-04
      • 2020-04-06
      • 2013-01-02
      • 2023-03-09
      • 1970-01-01
      • 2013-11-18
      相关资源
      最近更新 更多