Android: Modules built with SDK 10.2.0 crash on launch in older SDKs
Closed this issue ยท 14 comments
Description
Modules built with SDK 10.2.0 crash on launch in older SDKs. It must be some kind of regression in the core or V8 causing this.
Expected Behavior
They should not crash.
Actual behavior
They do crash.
Reproducible sample
Any app built with SDK 10.1.1 with a module built with 10.2.0
Steps to reproduce
- Create a new sample project (
ti create -t app
) - Make sure to have SDK 10.2.0 selected (
ti setup sdk
) - Compile a module of your choice
- Include the module in your sample project
- Run the app
Platform
Android
SDK version you are using
10.2.0
Alloy version you are using
No response
can confirm that:
- build my blurview module with 10.2.0
- added it to an app with 10.1.1.GA
- app will crash at startup with:
AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN2v88internal20CanHaveInternalFieldEi" referenced by "/data/app/~~K3uOgt4B0CpZGgaRR4UwsA==/com.miga.compeat-yHGxLGFDBQ8jmGCmXqsXCg==/lib/arm64/libti.blurview.so"...
AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1077)
AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:998)
AndroidRuntime: at java.lang.System.loadLibrary(System.java:1656)
AndroidRuntime: at org.appcelerator.kroll.runtime.v8.V8Runtime.loadExternalModules(V8Runtime.java:135)
AndroidRuntime: at org.appcelerator.kroll.runtime.v8.V8Runtime.initRuntime(V8Runtime.java:109)
AndroidRuntime: at org.appcelerator.kroll.KrollRuntime.doInit(KrollRuntime.java:217)
AndroidRuntime: at org.appcelerator.kroll.KrollRuntime.init(KrollRuntime.java:112)
AndroidRuntime: at com.miga.compeat.CompeatApplication.onCreate(CompeatApplication.java:67)
AndroidRuntime: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1223)
AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6762)
AndroidRuntime: at android.app.ActivityThread.access$1500(ActivityThread.java:256)
AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2091)
AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106)
AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:201)
AndroidRuntime: at android.os.Looper.loop(Looper.java:288)
AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7870)
AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
I'll see if I can debug something
workaround of course: build module with 10.2.0 and add minsdk 10.2.0
in the manifest or build with 10.1.1.GA
This should be the last V8 update: #13097
when I revert to 8.8.278.17
and build a 10.2.0, then rebuild the module and build my app with 10.1.1.GA including this module it won't crash!
Just searching around:
The CanHaveInternalField
part was added in this patch:
tidev/v8_titanium@fa92fc7#diff-4f2f329447fc899a9eadda6a27ac58bbb97ef773991b42367e35c73a15b5adcdR611-R612
but not being able to build a custom v8_titanium version (almost 10gb v8 files after first steps ๐ )
Careful: just wild guesses ๐
v8-object.h is the file that gets patch with the line above. So I've looked at the file and checked where the method is located. The methods are in api.cc
.
So I've looked at another method that is called from that file and found IsolateFromNeverReadOnlySpaceObject
a few lines above CanHaveInternalField
.
and that is the problematic (not found) call:
it's adding v8::
before internal
. Perhaps we have to get rid of v8::
? But on the other hand nodejs uses the same syntax.
Another option would be:
Just put the check back in that place and not use the function. It is
bool i::CanHaveInternalField(int instance_type) {
return instance_type == i::Internals::kJSObjectType ||
instance_type == i::Internals::kJSSpecialApiObjectType ||
v8::internal::InstanceTypeChecker::IsJSApiObject(
static_cast<v8::internal::InstanceType>(instance_type));
}
and in the old v8-object.h file the check was
instance_type == I::kJSApiObjectType ||
instance_type == I::kJSSpecialApiObjectType) {
which is the first half of the return value. So perhaps we could patch that back?
The good side: https://github.com/m1ga/v8_titanium/actions/runs/2180938399 the action is running!
We need to change the URL in https://github.com/tidev/v8_titanium/blob/master/.gitmodules to https://
Can't get it to run locally ๐ Got a bit further but still missing some header files
So it looks like the last V8 update is broken, the patch used to keep backward compatibility needs more fixes in it. I think that means as a first step rolling back this commit: e186ae1
@m1ga is on the general right track here. I don't have the exact fix, but I can at least give some context to work with, and hopefully @garymathews could also provide more background on typical dev workflow he used to get working patches to V8.
The relevant branch here is this one: https://github.com/tidev/v8_titanium/tree/9.4-lkgr
We tried to keep a branch for each V8 stable branch we targeted. Then we'd update the V8 submodule pointer to the tip of the equivalent V8 branch and work on patches to retain backwards compatibility. First cut was get V8 compiling, then we'd cut builds and open a branch/PR for titanium_mobile to point at the builds. (This was as simple as updating the android/package.json
with the new version number for us because the V8 builds would get uploaded to an S3 bucket that it would grab from. Not sure what you guys have set up her now). Then usually you can know pretty quickly if you run a quick local build and unit test run, because if you break backwards compatibility just trying to require any native Android module will typically crash. (And given that V8 cuts new branches every 6 weeks and doesn't even try to retain backwards compatibility, it often did!). The you have to iterate on the compatibility*.patch
files in our v8_titanium repo to alter the APIs and retain compatibility.
Alternately, you could decide to only update V8 on major releases of Titanium and always break Android native module backwards compatibility, but obviously that's not great for the community - which is why we went through these API patch hoops.
Also note that this web page is handy for keeping tabs on the V8 branches and status: https://omahaproxy.appspot.com
Typically you'd want to target the android stable row's version when you're planning to target a new V8.
Thansk for the insights @sgtcoolguy ๐
One quick question: where is your source file you create the patches from.
Trying to build a SDK with this V8 tomorrow: https://github.com/m1ga/v8_titanium/actions/runs/2191535617
I've changed the if
to the old one without the "missing" function
@m1ga Not sure what specifically you mean what is the source we build patches from. We apply the existing patches to the source of v8 via git, and then if we need to make further changes we do that manually and generate new patches via git diff
.
Looking at https://github.com/tidev/v8_titanium/blob/9.4-lkgr/build_mac_v8.sh is relatively useful as a sort of telling what's going on at a higher level when we build.
I should note that it may be useful to someday intentionally update to latest stable V8 and drop all the patches and break backwards compatibility to "start over" when all these patches get too unwieldy and it makes sense to. For example, some of these APIs were changed in a way that you could update our binding layer in Android to use the newer APIs for better overall performance (i.e. I believe some methods now have flags to tell V8 that the call is side-effect free and therefore the result can be cached, or some optimization flags can be kept on). But obviously breaking all existing native modules is a pain in the butt for the ecosystem.
Ah I see. I though you have an original "valid" file (like appc_v8-object.h) somewhere and diff that with every new v8 sources once they come out so it will always be your original file. But I think I understand it a bit better now. Will try to create a custom patch, the first one was just changing lines and adjust the patch line numbers ๐
I like the plain v8 idea but I think that is currently (at least for me) out of my knowledge to handle the changes
First again: So happy to hear from you Chris!
My 2 cents here: If we are not able to patch the V8 engine properly, we might want to stay on the old one (revert the last update) and move to the latest one in SDK 11.0.0 / 12.0.0, being okay to break modules. Until then, I mean, the old one works fine. And most of the users don't require stuff like WebAssembly in their Ti apps, so the eng-focus might be needed elsewhere.
I think it will be fine to stay with the old 10.1.1 V8 for 10.2.0. There are also 9.2 branch we could test.
But in 5 hours we will know more ๐ Started a new 9.4 build.
It helps to have the correct v8 branch when you want to apply the patches ๐คฆ
It worked! If you want to test it @hansemannn:
Change these two lines:
android/package.json
"integrity": "sha512-ykkShAXGn0g0LY7w7xx1QkUgfwMpJyREWgwN5bCIn+WqzMUArMfbmGIo/JnjGuTtR5b3cWZjGRT/V01Ozmf5yQ=="
and
android/titanium/libv8-services.js
const downloadUrl = 'https://migaweb.de/libv8-9.4.146.16-release.tar.bz2';
to download my v8 and build a local SDK
my patch: tidev/v8_titanium#55
Isn't this fixed with the PR?