NativeScript / NativeScript

⚡ Empowering JavaScript with native platform APIs. ✨ Best of all worlds (TypeScript, Swift, Objective C, Kotlin, Java, Dart). Use what you love ❤️ Angular, Capacitor, Ionic, React, Solid, Svelte, Vue with: iOS (UIKit, SwiftUI), Android (View, Jetpack Compose), Dart (Flutter) and you name it compatible.

Home Page:https://nativescript.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

newDrawable on NULL object crash in ui/styling/background.android.ts

Yermo opened this issue · comments

I do not know if this is a tns-core-modules issues, an android-runtime issue, or an issue with the nativescript-mapbox plugin that I am working on.

I originally filed this with the android-runtime project here: NativeScript/android#1487

Environment

  • CLI: 6.1.2
  • Cross-platform modules: 6.1.1
  • Android Runtime: 6.1.2
  • iOS Runtime:
  • Plugin(s):
  "dependencies": {
    "@angular/animations": "~8.2.0",
    "@angular/common": "~8.2.0",
    "@angular/compiler": "~8.2.0",
    "@angular/core": "~8.2.0",
    "@angular/forms": "~8.2.0",
    "@angular/platform-browser": "~8.2.0",
    "@angular/platform-browser-dynamic": "~8.2.0",
    "@angular/router": "~8.2.0",
    "nativescript-advanced-permissions": "^1.2.0",
    "nativescript-mapbox": "file:../publish/dist/package",
    "nativescript-angular": "~8.2.0",
    "nativescript-theme-core": "~1.0.6",
    "nativescript-ui-sidedrawer": "~7.0.0",
    "reflect-metadata": "~0.1.12",
    "rxjs": "^6.4.0",
    "rxjs-compat": "^6.5.3",
    "tns-core-modules": "~6.1.0",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular/compiler-cli": "~8.2.0",
    "@ngtools/webpack": "~8.2.0",
    "@types/chai": "~4.1.7",
    "@types/mocha": "~5.2.5",
    "@types/node": "~10.12.18",
    "chai": "~4.1.2",
    "codelyzer": "~4.5.0",
    "mocha": "~5.2.0",
    "mocha-junit-reporter": "~1.18.0",
    "mocha-multi": "~1.0.1",
    "mochawesome": "~3.1.2",
    "nativescript-dev-appium": "^6.1.2",
    "nativescript-dev-webpack": "~1.2.0",
    "node-sass": "^4.7.1",
    "tslint": "~5.19.0",
    "typescript": "~3.5.3"
  }

Using Android Emulator with an API 28 image under Ubuntu 18.04 LTS with Android Studio:

Android Studio 3.5
Build #AI-191.8026.42.35.5791312, built on August 8, 2019
JRE: 1.8.0_202-release-1483-b49-5587405 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Linux 4.15.0-38-generic

Describe the bug

I am working on the NativeScript Mapbox plugin. My fork is here: https://github.com/Yermo/nativescript-mapbox

The crash can be replicated using the included demo-angular app and e2e test.

Since upgrading Nativescript to NS 6+, I am experiencing a random crash when navigating away from a page containing a map and removing the map container when running with "markingMode":"none".

I do not know if the map plugin code is causing the instability as I have not been able to reproduce this problem navigating away from other pages, but the crash happens after the navigation has completed and the map view and object have been destroyed leading me to believe that maybe this is not my bug.

The map object is quite large so when doing lateral navigation ideally I want to destroy the mapbox view. I do this by wrapping the Mapbox tag in container with an *ngIf. Before navigating away the *ngIf condition is set to false and I wait for the mapbox onDestroy to return before proceeding with the navigation (thinking maybe there's a race condition somewhere.)

After a random number of navigations between the map page and the test-crash page in the demo-angular app, it will crash on

defaultDrawable = cachedDrawable.newDrawable(nativeView.getResources());

when navigating /to/ the test-crash page with the error:

JNI DETECTED ERROR IN APPLICATION: can't call android.graphics.drawable.Drawable android.graphics.drawable.ColorDrawable$ColorState.newDrawable(android.content.res.Resources) on null object

cachedDrawable in this case is not null on the javascript side so I suspect a markingMode: "none" issue. Adding a line of code to the javascript:

if ( cachedDrawable == null ) {
	console.log( "background.android.js - cachedDrawable is NULL ---------------" );
} else {
        console.log( "background.android.js - cachedDrawable is:", cachedDrawable );
}

Causes a crash on the second console.log with the error can't call toString() on null object.

To Reproduce
Clone my repository:
https://github.com/Yermo/nativescript-mapbox

cd nativescript-mapbox/src
npm run build.dist
cd ../demo-angular
tns build android
npm run e2e -- --runType android28

(or whatever emulator you have)
It will crash between 3 and 100 iterations of navigating between the map page and the crash-test page.

Expected behavior

Ideally, it should not crash.

Sample project
https://github.com/Yermo/nativescript-mapbox/demo-angular

Additional context
I am motivated to solve this problem as it is a blocking issue for me that has cost me a few weeks now.
It is entirely possible that something I am doing in my plugin is mucking up the works, but I have attempted to follow all the guides and recommendations for writing plugins. I am not the original Mapbox plugin author but am largely taking over development of that plugin.

If no one has the free cycles to look into this, could I maybe get some pointers on how I might try to track this down?
Is there a way to test a NativeScript/Javascript object to see if the corresponding Java object has been freed or is set to NULL?

As an additional data point, if I set defaultDrawable to null instead of cachedDrawable.newDrawable(...) on line 86, I am unable to reproduce the crash.

@Yermo it seems that there are some similar issue logged in the nativescript-mapbox repository (e.g. this one) and this one

Yup. Those have been long standing bugs, however I have those two fixed in my fork ( at least I think I do ... I'm getting ready to merge back in once I get a few more things resolved.)

This bug is in tns-core-modules and seems to have to do with setting class.selected in the rad side drawer. For some reason (see above), cachedDrawable is NULL on the java side and not on the javascript side implying some reference to the cachedDrawable is not being correctly saved on the javascript side.

If I just set it to NULL, then the crash no longer happens.

Others have apparently run into the same crash without the use of a map, so at this point I'm pretty confident it is not my bug and doesn't have anything to do with the mapbox plugin.

I think I've been running into the same issue in my project, this time not by navigating repeatedly, but scrolling quickly a list view with dynamic images. Setting cachedDrawable to NULL also seems to prevent the crash. Removing the images makes the crash less likely to happen, but it still happens eventually.

We've been having issues with the mapbox plugin as well, and this seems to be the main cause (crash when navigating away from the component with the map), getting this fixed would be amazing !

@NativeScript Team : do you have any new about this bug ?

I don't know if everybody is in my case, but from now, I'm locked to nativescript 6.2.0 (and tns-core-modules 6.1.0).
If I upgrade one of those library, I get a crash, depending on the tns-core-module version :

  • on >= 6.3.0, all the navigation actions in the app will make a crash
  • on >= 6.2.0 and < 6.3.0, it only crashes when the navigation goes back to a page where a mapBox map is present,
  • on > 6.1.0 and < 6.2.0, the navigation displays the page previously called in the router (during less than a second) and then displays the target page (while navigating in a nested page-router-outlet).

In summary, there is a big mess on all version > 6.2.0

Closing as resolved via #8320

we were hitting this as well with {N} 6.4 - glad to see it fixed!

@Yermo @NickIliev I noticed that this was fixed in 6.4.2 already, which we use but we still see the crash.

If I patch the line mentioned by @Yermo, I do not see the crash. So in our case it's not the cachedDrawable being null but a GC issue. Essentially the same as Yermo concludes here.

Note: we do not use any plugin, just plain {N} and Angular. We do however use an inline binding that manipulates CSS styles and thus the background of some UI elements. Once we remove the inline CSS manipulation, the crash is not seen.

I think for our next scheduled app release we will just monkey patch background.android.js.

@Yermo any update on the fork you mentioned?

@lambourn I'm taking over the mapbox nativescript plugin. I've just been slammed for months longer than expected with a project that's taking all my time, amongst other distractions. Check out my fork here which fixes most issues: https://github.com/Yermo/nativescript-mapbox

this will get merged into the official repository soon, I hope. I've just got to find a few hours.

@Yermo thanks, I'll have a look.

I understand that you fixed the issue directly in your fork of the mapbox plugin while I thought you fixed the issue in a fork of @nativescript/core itself.

I run into the "Attempt to use cleared object reference" issue, but neither mapbox nor any other 3rd party plugin is in use in this case.

Root cause for the crash is inline CSS manipulation which updates the background:

<StackLayout [ngClass]="{'placeholder-overlay': true, 'indicate-disabled': isControlsDisabled}"></StackLayout>

scss:

.placeholder-overlay {
    width: 100%;
    height: 100%;
    &.indicate-disabled {
        background-color: rgba(#fff, 0.4);
    }
}

@lambourn Brain fault on my part. The issue is in tns-core-modules. Check my comment in this thread above. I thought they had fixed it.

@Yermo ok, no worries.

The monkey-fix/-patch you mention above resolves the crash for me.

The recent fix/PR does not fix it.

@Yermo can you check the latest fix here #8475 ?

@vtrifonov I'll be happy to. Has this been merged into a version released on NPM or do I need to build it? I just a few pointers and I'll be happy to run my tests against it.