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.
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.
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
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 )
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);
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 ?
@mayardb probably related to updating the underlying geojsonsource.
@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).
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).
~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 https://github.com/mapbox/mapbox-gl-native/issues/9688#issuecomment-373004990)
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.
I'm jumping in and reporting the same exact thing, moving of camera + LocationLayerPlugin make the app generate hundreds of lines of Warnings.
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.
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
Also experiencing this with locationplugin
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?
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 https://github.com/mapbox/mapbox-plugins-android/pull/426 for reference.
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.
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!
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)
))
);
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.
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. 馃槃
Most helpful comment
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).