How can I detect which javascript engine (v8 or JSC) is used at runtime in Android?

I think the better question is: Why do you care? You're basically falling into the "browser detection" trap that a lot of people fell into in the late 90's / early 00's. Since then, though, we've learned that it's feature detection that's the more useful approach, not least because the features supported in a given browser were (mostly) a moving target. There's code now, running on IE9 with its dramatically-improved DOM and JavaScript support, that's not using those features because it's doing browser detection and falling back on IE6 techniques.

So rather than worrying about V8 vs. JSC, just worry about the features you want. I don't know anything about JSC, but for instance let's assume it doesn't have the forEach method on arrays that V8 has (part of the ECMAScript 5th edition standard). Rather than throwing a big "V8 vs. JSC" lever, you'd do:

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

(Your "code that falls back" might add forEach to the prototype, or maybe this test is in your own iterator function and you want to know whether to defer to a native implementation or supply your own.)

And similarly for other features you want to use that may or may not be present.


But if you really need to detect V8 vs. JSC (and from your comment it seems you may), this page seems to demonstrate a means of doing so, though it seems awfully fragile. Here's my slightly-edited version (not least to replace window.devicePixelRatio with the test for WebkitAppearance — the former gives false positives on at least some other browsers [Firefox, for instance, which uses Gecko, not 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");
}

Works for me detecting the difference between Chrome (which also uses V8) and Safari (which also uses JSC).


Although the answer above points out the best methods, I thought I'd point out another way of doing this from inside a native library.

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

The exported symbols are mangled, unfortunately, so there is no 100% guarantee that the compiler used by your firmware manufacturer mangled the symbol in the same way (use nm --defined-only libwebcore.so -g on a library with symbols). One would expose this function via the JNI and check from inside Java code.

The libwebcore.so library also lists V8_Fatal as one of the symbols, which is not susceptible to mangling.

JSC will have some other exported symbols that you can check for from inside a native library. If both are non-existent you can fallback to other methods.