-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Load jsc or hermes lib in static method #30749
Conversation
Hi @iqqmuT! Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. If you have received this in error or have any questions, please contact us at cla@fb.com. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code analysis results:
google-java-format
found some issues. See https://github.com/google/google-java-format
ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.java
Outdated
Show resolved
Hide resolved
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Base commit: 65975dd |
Base commit: 65975dd |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Summary: See the comments for more info. Changelog: [Android] [Changed] - Improve exception message when JSC loading fails Reviewed By: tmikov Differential Revision: D19917034 fbshipit-source-id: d846f542c31e9c94edcee240c2935d77d48d1f2a
@sota000 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @iqqmuT, apologies for taking a long time to get back to you. I've left a comment about removing the "loaded" check. Could you please check it out when you have a chance? Thank you!
ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.java
Outdated
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @iqqmuT! Thanks for addressing the comment! I assume you have tested that it works without the check?
@sota000 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
Yes I tested it and it worked perfectly. |
@iqqmuT, the CI seems to fail consistently with this change. Would you ming taking a look if they are relevant to your changes? (I can help fix the lint one) |
@sota000 I couldn't check Facebook internal tests but ci/circleci test failures don't seem to be relevant to my changes. |
@iqqmuT I think that you must to add a new empty line between Like this:
|
@sota000 seems that the tests failed for a reason not related to this PR. This is the output of the tests:
And then in the next test:
|
@sota000 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
Summary: Many have reported about the misguiding error `Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes.so` even though they don't use Hermes (for example issues #26075 #25923). **The current code does not handle errors correctly when loading JSC or Hermes in `ReactInstanceManagerBuilder`**. **ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java:** ```java try { return new HermesExecutorFactory(); } catch (UnsatisfiedLinkError hermesE) { // We never get here because "new HermesExecutorFactory()" does not throw an exception! hermesE.printStackTrace(); throw jscE; } ``` In Java, when an exception is thrown in static block, it will be RuntimeException and it can't be caught. For example the exception from `SoLoader.loadLibrary` can't be caught and it will crash the app. **ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java:** ```java static { // Exception from this code block will be RuntimeException and it can't be caught! SoLoader.loadLibrary("hermes"); try { SoLoader.loadLibrary("hermes-executor-debug"); mode_ = "Debug"; } catch (UnsatisfiedLinkError e) { SoLoader.loadLibrary("hermes-executor-release"); mode_ = "Release"; } } ``` This PR fixes the code so that the original exception from failed JSC loading is not swallowed. It does not fix the original issue why JSC loading is failing with some devices, but it can be really helpful to know what the real error is. For example Firebase Crashlytics shows wrong stack trace with current code. I'm sure that this fix could have been written better. It feels wrong to import `JSCExecutor` and `HermesExecutor` in `ReactInstanceManagerBuilder.java`. However, the main point of this PR is to give the idea what is wrong with the current code. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [Android] [Fixed] - Fix error handling when loading JSC or Hermes Pull Request resolved: #30749 Test Plan: * from this PR, modify `ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.java` so that JSC loading will fail: ```java // original SoLoader.loadLibrary("jscexecutor"); // changed SoLoader.loadLibrary("jscexecutor-does-not-exist"); ``` * Run `rn-tester` app * Check from Logcat that the app crashed with correct exception and stacktrace. It should **not** be `java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes.so` Tested with Hermes ``` SoLoader.loadLibrary("hermes-executor-test"); ``` Got this one in logcat ``` 09-24 20:12:39.552 6412 6455 E AndroidRuntime: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes-executor-test.so ``` Reviewed By: cortinico Differential Revision: D30346032 Pulled By: sota000 fbshipit-source-id: 09b032a9e471af233b7ac90b571c311952ab6342
…16099) # Why fix crash when `enableHermes: true` with dev-menu on react-native 0.67. i tested it from bare-expo. stacktrace: ``` FATAL EXCEPTION: main Process: dev.expo.payments, PID: 18344 java.lang.NoClassDefFoundError: com.facebook.react.jscexecutor.JSCExecutor at com.facebook.react.jscexecutor.JSCExecutor.loadLibrary(JSCExecutor.java:24) at com.facebook.react.ReactInstanceManagerBuilder.getDefaultJSExecutorFactory(ReactInstanceManagerBuilder.java:352) at com.facebook.react.ReactInstanceManagerBuilder.build(ReactInstanceManagerBuilder.java:319) at com.facebook.react.ReactNativeHost.createReactInstanceManager(ReactNativeHost.java:95) at expo.modules.devmenu.DevMenuHost.createReactInstanceManager(DevMenuHost.kt:41) at com.facebook.react.ReactNativeHost.getReactInstanceManager(ReactNativeHost.java:42) at expo.modules.devmenu.DevMenuManager.maybeInitDevMenuHost$lambda-8(DevMenuManager.kt:169) at expo.modules.devmenu.DevMenuManager.lambda$rZDvUiNHHHvkcRmdKO265huCv6U(Unknown Source:0) at expo.modules.devmenu.-$$Lambda$DevMenuManager$rZDvUiNHHHvkcRmdKO265huCv6U.run(Unknown Source:0) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) Caused by: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libjscexecutor.so SoSource 0: com.facebook.soloader.ApkSoSource[root = /data/data/dev.expo.payments/lib-main flags = 1] SoSource 1: com.facebook.soloader.DirectorySoSource[root = /data/app/~~ibMyBupkSRJXdt_c772rhw==/dev.expo.payments-ru7gzQ9g2MilqIhz24Lduw==/lib/arm64 flags = 0] SoSource 2: com.facebook.soloader.DirectorySoSource[root = /vendor/lib64 flags = 2] SoSource 3: com.facebook.soloader.DirectorySoSource[root = /system/lib64 flags = 2] Native lib dir: /data/app/~~ibMyBupkSRJXdt_c772rhw==/dev.expo.payments-ru7gzQ9g2MilqIhz24Lduw==/lib/arm64 ``` the first time to create a `ReactInstanceManager`, it successes. however, the second time to create a `ReactInstanceManager` for dev-menu, it crashes with `NoClassDefFoundError`. it's also uncaughtable [here](https://github.com/facebook/react-native/blob/20b9ed91c02a0cbf2f970bf51ccc4c278c63540c/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java#L348-L354) this is because the change landed in react-native 0.67: facebook/react-native#30749 according to jvm spec v2 2.17.5, ([maybe from this spec](https://docs.oracle.com/javase/specs/jvms/se6/html/Concepts.doc.html#24237)). the second time to load a failure class, the vm throws `NoClassDefFoundError`. [there's another reference in android art vm implementation](https://android.googlesource.com/platform/art/+/ec696e5d98ae4c503966f199bac341b50bfa1a5b/runtime/class_linker.cc#478) # How for dev-menu, we try to locate `libjsc.so` and create specific javascript executor. # Test Plan tested on my react-native 0.67 upgrade branch: #16038
Summary
Many have reported about the misguiding error
Fatal Exception: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes.so
even though they don't use Hermes (for example issues #26075 #25923).The current code does not handle errors correctly when loading JSC or Hermes in
ReactInstanceManagerBuilder
.ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java:
In Java, when an exception is thrown in static block, it will be RuntimeException and it can't be caught. For example the exception from
SoLoader.loadLibrary
can't be caught and it will crash the app.ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java:
This PR fixes the code so that the original exception from failed JSC loading is not swallowed. It does not fix the original issue why JSC loading is failing with some devices, but it can be really helpful to know what the real error is. For example Firebase Crashlytics shows wrong stack trace with current code.
I'm sure that this fix could have been written better. It feels wrong to import
JSCExecutor
andHermesExecutor
inReactInstanceManagerBuilder.java
. However, the main point of this PR is to give the idea what is wrong with the current code.Changelog
[Android] [Fixed] - Fix error handling when loading JSC or Hermes
Test Plan
ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.java
so that JSC loading will fail:rn-tester
appjava.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes.so