Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Attempt to remove non-JNI local reference, dumping thread #9688

Closed
tobrun opened this issue Aug 2, 2017 · 21 comments
Closed

Attempt to remove non-JNI local reference, dumping thread #9688

tobrun opened this issue Aug 2, 2017 · 21 comments
Labels
Android Mapbox Maps SDK for Android

Comments

@tobrun
Copy link
Member

tobrun commented Aug 2, 2017

We have been hearing complaints about the following log message:

Attempt to remove non-JNI local reference, dumping thread

Capturing from a Chromium issue:

Whenever the parameters passed from Java to a JNI method (i.e. the incoming jobject parameters) are wrapped in a ScopedLocalJavaRef, this causes them to be deleted once they go out of scope with JNIEnv::DeleteLocalRef. On recent versions of ART with CheckJNI turned on, this causes a spammy warning to be printed to logcat stating "Attempt to remove non-JNI local reference, dumping thread" with a thread dump, as apparently parameters are not supposed to be deleted, only objects returned as local references from native->java JNI calls. This is not actually a problem since the runtime just does nothing in this case (other than printing the warning)

Discussion and related commits can be found in chromium/506850.

@tobrun
Copy link
Member Author

tobrun commented Aug 17, 2017

I'm also seeing a lot of:

W/art: Attempt to remove local handle scope entry from IRT, ignoring

On a Samsung Galaxy J3 when playing around with GeoJSON sources.

@R0B3RDV
Copy link

R0B3RDV commented Sep 29, 2017

I can tell you: its not related to mapbox. My guess it has something to do what I found in my logs ActivityManager: Unable to start service Intent { act=com.google.android.gms.ads.identifier.service.START pkg=com.google.android.gms } U=0: not found, then after a couple of seconds: art : Attempt to remove non-JNI local reference, dumping thread

@davols
Copy link

davols commented Dec 29, 2017

It's related to some components of Mapbox.

(I'm right now debugging something else, semi related). But seeing a lot of those lines in the logs. And they have the same PID as the activity that uses mapbox (and NavigationView over at https://github.com/mapbox/mapbox-navigation-android )

@cvance
Copy link

cvance commented Jan 26, 2018

I was able to track this log down to this exact method (but not sure if its limited too, I see the log a ton but I also call this method a ton)

map.queryRenderedFeatures(mapRectF, filter);

@mayardb
Copy link
Contributor

mayardb commented Feb 12, 2018

Using genymotion, I notice I have this bug when activating the hardware gps location.

Is that possible that it is linked to the mapbox-android-plugin-locationlayer when receiving location ?

@tobrun
Copy link
Member Author

tobrun commented Feb 12, 2018

@mayardb probably related to updating the underlying geojsonsource.

@osana
Copy link
Contributor

osana commented Feb 17, 2018

@tobrun I could reproduce this in master in Query Source Features
To see it: zoom out, tap on land to get features.

It does happen when calling source.querySourceFeatures but it seems to be happening before it hits geojson native (that was recently modified).

@danetch
Copy link

danetch commented Feb 19, 2018

I found it happens a lot when using the new location layer plug-in, as mentioned by @mayardb - when I disable the plugin, my logcat is back to normal (only 2 lines of "Attempt to remove non-jni ...", against hundreds).

@LukasPaczos
Copy link
Contributor

LukasPaczos commented Mar 14, 2018

I'm able to reproduce this issue with Xperia Z3, where Attempt to remove non-JNI local reference, dumping thread fires constantly, even up to 4-5 times per millisecond and Pixel 2 where it's a bit tamed.

On both devices, it seems like it fires only when the camera is transitioning. If its still, GeoJsonSource updates don't seem to generate this logs.

(this is implementation specific because we are calling Layer#setProperties on every camera move in the LocationLayerPlugin, see #9688 (comment))

@vicobz
Copy link

vicobz commented Mar 14, 2018

I've also been facing this issue for several months and still encounter it. I get thousands of these logs in few seconds when I launch my app. I use the LocationLayerPlugin too, as mentioned above.

@albert0m
Copy link

I'm jumping in and reporting the same exact thing, moving of camera + LocationLayerPlugin make the app generate hundreds of lines of Warnings.

@LukasPaczos
Copy link
Contributor

It looks like it's logged whenever SymbolLayers icon rotation is changed, either due to setting a new icon-rotation manually or the camera changing position while icon-rotation-alignment is set to map and heading of the layer has to be recalculated.

@LukasPaczos
Copy link
Contributor

Furthermore, I can confirm that every single call to paint or layout property setters from the JNI results in Attempt to remove non-JNI local reference, dumping thread. Not the case for calls from core.

I have a hunch that it happens during the values conversion, but would love to have some additional eyes on it.

/cc @ivovandongen

@jethromayuk
Copy link

Also experiencing this with locationplugin

@callingmedic911
Copy link

callingmedic911 commented Jul 6, 2018

Having same issue, when using ValueAnimator to change icon size of INFINITE duration.

ValueAnimator markerAnimator = new ValueAnimator();
markerAnimator.setObjectValues(1f, 1.5f, 1f);
markerAnimator.setDuration(1200);
markerAnimator.setRepeatCount(ValueAnimator.INFINITE);
markerAnimator.addUpdateListener(animation ->  symbolLayer.setProperties(
        iconSize(switchCase(
                get("suggested"), literal((float) markerAnimator.getAnimatedValue()),
                literal(1f)
                )
        )
));
markerAnimator.start();

It is causing so much log spam, that it reaches limit after few minutes. I've re-plug after minutes. Such a pain when debugging. Is there any workaround?

@LukasPaczos
Copy link
Contributor

Yes, as mentioned before, this log will appear with every Layer#setProperties call. To workaround that you need to provide data with JSON features + Expressions rather than properties setters. See mapbox/mapbox-plugins-android#426 for reference.

@callingmedic911
Copy link

callingmedic911 commented Jul 6, 2018

Thanks for your prompt response.
If I understand correctly, I have to use something like this:

symbolLayer.setProperties(
        iconImage(switchCase(
                get("active"), literal("poi-active"),
                get("visited"), literal("poi-visited"),
                literal("poi-unvisited")
                )
        )
);

If so, that I'm already doing for ^ such properties. But for animating iconSize up and down continuously I've used ValueAnimator. Is there any Expression equivalent for the same?

Thanks for your help.

@LukasPaczos
Copy link
Contributor

Yes, that would be correct. In the animation example above you are not really leveraging data-driven nature of expressions but resetting the value every time manually. This should look more like this:

markerAnimator.addUpdateListener(animation ->  {
        animatedPoiFeature.addNumberProperty("animation_progress", (float) markerAnimator.getAnimatedValue());
        source.setGeoJson(featureCollection)
}));

Where animatedPoiFeature is the POI you want to animate and featureCollection is the collection that the POI is a part of. All non-animated POIs would have the "animation_progress" property set to 1. The layer would be initially set up like this:

symbolLayer.setProperties(
        iconImage(switchCase(
                get("active"), literal("poi-active"),
                get("visited"), literal("poi-visited"),
                literal("poi-unvisited")
                )
        ),
        iconSize(get("animation_progress"))
);

I hope this helps!

@callingmedic911
Copy link

callingmedic911 commented Jul 6, 2018

Thanks Lucas,

I just implemented this and one question: is this just placebo or there is noticeable performance impact using this?
Updating GeoJSON:

markerAnimator.addUpdateListener(animation -> {
    if (nextPoint != null) {
        nextPoint.addNumberProperty("icon-size", (float) animation.getAnimatedValue());
        mapData.setGeoJson(geojson);
    }
});

Expression:

symbolLayer.setProperties(
        iconImage(switchCase(
                get("active"), literal("poi-active"),
                get("visited"), literal("poi-visited"),
                literal("poi-unvisited")
                )
        ),
        iconSize(switchCase(
                get("suggested"), get("icon-size"),
                literal(1f)
        ))
);

@LukasPaczos
Copy link
Contributor

Unfortunately, there might be a performance impact, especially if your data-set is big.
In this case, I'd recommend "moving" the animated POIs to another, more compact source.

Another possibility would be using TransitionOptions but those are not supported by expressions yet, and the issue of continues logs would return. There wouldn't be as much pollution, but still. You can find an example of TransitionOptions usage in our TestApp.

@callingmedic911
Copy link

About data-set, it is just 2 Symbol and 2 Polygon. For now, I'll stick with DDS solution to suppress warnings but in case it affects performance severely, then will split moving point from original source. What do you think?
TransitionOptions would be suitable if there is one time change in value. But in my case, it's infinite repeat.

Thanks for all the help. 😄

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android
Projects
None yet
Development

No branches or pull requests