Titanium JIRA Archive
Appcelerator Modules (MOD)

[MOD-2378] Android: Memory leak - TiBlob: (main) getNativePath not supported for non-file blob types.

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2018-03-01T00:02:31.000+0000
Affected Version/sn/a
Fix Version/sRelease 7.1.0
ComponentsMap
Labelsandroid, annotation, customView, image, ti.map
ReporterOnur Yıldırım
AssigneeGary Mathews
Created2017-12-11T01:33:10.000+0000
Updated2018-07-13T14:55:02.000+0000

Description

Adding annotation with customView to a map outputs this warning for every annotation. This blocks the performance when you have 70+ markers. TiBlob: (main) [1106,1935] getNativePath not supported for non-file blob types. To reproduce, just do this in your map complete event handler:
function onMapComplete(event) {
	var annot = TI_MAP.createAnnotation({
		latitude: 41.071004,
		longitude: 29.015450,
		title: 'test #1',
		customView: Ti.UI.createImageView({
			image: '/images/marker.png',
			width: Ti.UI.SIZE,
			height: Ti.UI.SIZE
		})
	});
	$.mapView.addAnnotation(annot);
}
Here is the [line in TiBlob.java](https://github.com/appcelerator/titanium_mobile/blob/30a9911c4f1d30ba0c3d971903f16ae8cc18b0a6/android/titanium/src/java/org/appcelerator/titanium/TiBlob.java#L526). getNativePath() should not be called in the first place bec. customView already provides the annotation view. Why would it try to get a path for it? Why I use customView? Bec. otherwise if I use the image property, it leaks memory on Android; if you remove and re-add annotations multiple times... I'm tired of Titanium! *UPDATE 1:* It still leaks memory both when .image or .customView used. Doesn't matter. *UPDATE 2:* It also leaks memory when using default pins (not setting .image or .customView) but the app stands a bit more longer before it crashes.
[WARN] :   art: Throwing OutOfMemoryError "Failed to allocate a 57612 byte allocation with 55816 free bytes and 54KB until OOM"
[WARN] :   JNIHelp: Discarding pending exception (java.lang.OutOfMemoryError: Failed to allocate a 57612 byte allocation with 55816 free bytes and 54KB until OOM) to throw java/lang/RuntimeException
[WARN] :   W/System.err: java.lang.RuntimeException: Could not allocate java pixel ref.
[WARN] :   W/System.err: 	at android.graphics.Bitmap.nativeCreateFromParcel(Native Method)
[WARN] :   W/System.err: 	at android.graphics.Bitmap.-wrap0(Bitmap.java)
[WARN] :   W/System.err: 	at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1564)
[WARN] :   W/System.err: 	at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1563)
[WARN] :   W/System.err: 	at bsb.a(:com.google.android.gms@11509470:2)
[WARN] :   W/System.err: 	at wpl.onTransact(:com.google.android.gms@11509470:8)
[WARN] :   W/System.err: 	at android.os.Binder.transact(Binder.java:499)
[WARN] :   W/System.err: 	at com.google.android.gms.internal.zzed.zza(Unknown Source)
[WARN] :   W/System.err: 	at com.google.android.gms.maps.model.internal.zzc.zzd(Unknown Source)
[WARN] :   W/System.err: 	at com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(Unknown Source)
[WARN] :   W/System.err: 	at ti.map.AnnotationProxy.handleImage(AnnotationProxy.java:272)
[WARN] :   W/System.err: 	at ti.map.AnnotationProxy.processOptions(AnnotationProxy.java:232)
[WARN] :   W/System.err: 	at ti.map.TiUIMapView.addAnnotation(TiUIMapView.java:438)
[WARN] :   W/System.err: 	at ti.map.ViewProxy.handleAddAnnotation(ViewProxy.java:282)
[WARN] :   W/System.err: 	at ti.map.ViewProxy.handleAddAnnotations(ViewProxy.java:325)
[WARN] :   W/System.err: 	at ti.map.ViewProxy.addAnnotations(ViewProxy.java:313)
[WARN] :   W/System.err: 	at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method)
[WARN] :   W/System.err: 	at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62)
[WARN] :   W/System.err: 	at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:934)
[WARN] :   W/System.err: 	at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1157)
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[WARN] :   W/System.err: 	at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:363)
[WARN] :   W/System.err: 	at android.os.Handler.dispatchMessage(Handler.java:98)
[WARN] :   W/System.err: 	at android.os.Looper.loop(Looper.java:154)
[WARN] :   W/System.err: 	at android.app.ActivityThread.main(ActivityThread.java:6119)
[WARN] :   W/System.err: 	at java.lang.reflect.Method.invoke(Native Method)
[WARN] :   W/System.err: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
[WARN] :   W/System.err: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
[ERROR] :  TiExceptionHandler: (main) [6051,31629] ----- Titanium Javascript Runtime Error -----
[ERROR] :  TiExceptionHandler: (main) [0,31629] - In /alloy/controllers/index.js:101,13
[ERROR] :  TiExceptionHandler: (main) [0,31629] - Message: Uncaught Could not allocate java pixel ref.
[ERROR] :  TiExceptionHandler: (main) [0,31629] - Source: 				$.vwMap.addAnnotations(annots);
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: WaitForGcToComplete blocked for 21.152ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: WaitForGcToComplete blocked for 16.867ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: WaitForGcToComplete blocked for 21.218ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[ERROR] :  V8Exception: Exception occurred at /alloy/controllers/index.js:101: Uncaught Could not allocate java pixel ref.
[ERROR] :  V8Exception: Could not allocate java pixel ref.
[INFO] :   Choreographer: Skipped 83 frames!  The application may be doing too much work on its main thread.
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: WaitForGcToComplete blocked for 15.277ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[ERROR] :  EGL_emulation: tid 29011: eglSurfaceAttrib(1174): error 0x3009 (EGL_BAD_MATCH)
[WARN] :   OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xcb0fc420, error=EGL_BAD_MATCH
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: WaitForGcToComplete blocked for 35.539ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: WaitForGcToComplete blocked for 24.297ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: Alloc partial concurrent mark sweep GC freed 67(2456B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 357us total 21.130ms
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: Alloc concurrent mark sweep GC freed 3(72B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 261us total 21.652ms
[INFO] :   art: Forcing collection of SoftReferences for 64KB allocation
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 111MB to 96MB
[INFO] :   art: Alloc concurrent mark sweep GC freed 3(72B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 235us total 21.648ms
[WARN] :   art: Throwing OutOfMemoryError "Failed to allocate a 65548 byte allocation with 32104 free bytes and 31KB until OOM"
[INFO] :   art: WaitForGcToComplete blocked for 68.092ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: WaitForGcToComplete blocked for 67.564ms for cause Background
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: Waiting for a blocking GC Alloc
[INFO] :   art: Clamp target GC heap from 109MB to 96MB
[INFO] :   art: Alloc partial concurrent mark sweep GC freed 3632(322KB) AllocSpace objects, 29(1740KB) LOS objects, 2% free, 93MB/96MB, paused 199us total 19.395ms
[INFO] :   art: WaitForGcToComplete blocked for 21.957ms for cause Alloc
[INFO] :   art: Starting a blocking GC Alloc
[INFO] :   art: WaitForGcToComplete blocked for 18.575ms for cause Background
[INFO] :   APSAnalyticsService: Analytics Service Started
[INFO] :   APSAnalyticsService: Stopping Analytics Service
*Environment:* macOS High Sierra, node 8.9.3, Ti SDK 7.0.0, javac 1.8.0_112 Last Android device tested: Samsung Galaxy S7, Android 7.1.0 (API 25)

Attachments

FileDateSize
map-annot-test.zip2017-12-11T19:05:05.000+000010035760
marker.png2018-01-13T00:03:38.000+00004689
mleak-app-screen.png2017-12-11T19:05:38.000+0000886429
mleak-full-logs.txt.zip2017-12-11T19:10:54.000+000029914

Comments

  1. Mostafizur Rahman 2017-12-11

    Hello [~onury], Thanks for sharing with us. Can you please share the the full sample code to reproduce the issue on our end? Also provide share your android device information and console logs. Best
  2. Onur Yıldırım 2017-12-11

    @Mostafizur Rahman , I've attached a very explanatory sample app, full logs and more info (including environment, etc). I hope this helps you identify the problem quickly because our production app keeps crashing and we're loosing reputation over this. At least a workaround is crucial at this point. Pls let me know if you need anything else. Best,
  3. Onur Yıldırım 2017-12-11

    Updated the sample app to show it also leaks memory with default pins. But cannot upload anymore files.
  4. Onur Yıldırım 2017-12-13

    Any news on this? At least a confirmation pls.
  5. Onur Yıldırım 2017-12-15

  6. Onur Yıldırım 2017-12-16

    Please see the links below that discuss OutOfMemoryException when using maps in native Android. Might be helpful... * [StackOverflow: 75 markers on Map - memory leaks - OutOfMemoryException](https://stackoverflow.com/questions/14186072/75-markers-on-map-memory-leaks-outofmemoryexception) * [StackOverflow: Android - Many OutOfMemoryError exceptions only on single Activity with MapView](https://stackoverflow.com/questions/14186072/75-markers-on-map-memory-leaks-outofmemoryexception) * [Google Issue Tracker: Memory leak in system when using MapView](https://issuetracker.google.com/issues/36907271)
  7. Onur Yıldırım 2017-12-16

    Additional notes: - Adding <application android:largeHeap="true"> does not help. Still crashes. (not a guaranteed solution anyway). - Modifying ti.map module by using .release() for bitmap didn't help. (M. Gangolf) - Modifying ti.map module by manually calling gc() in removeAllAnnotations() didn't help. (M. Gangolf) - As a workaround; considered updating annotations without removing and re-adding but .image can be only set at creation-time. (And it would still leak anyway without a fix.)
  8. Sharif AbuDarda 2017-12-16

    Hello, We have verified the issue. Our engineers are working on it. The will schedule it for a fix. Thanks.
  9. Onur Yıldırım 2017-12-16

    Great! Thanks Sharif. Looking forward to that.
  10. Onur Yıldırım 2017-12-20

    @Sharif AbuDarda any kind of news on this?
  11. Onur Yıldırım 2018-01-12

    Still no updates on this.
  12. Eric Merriman 2018-01-12

    Hello [~onury], sorry to say the process failed us here. But this looks like a bad one so will ask our senior Android dev to look at this today. Expect some info by end of day.
  13. Onur Yıldırım 2018-01-12

    Looking forward to it. Thanks.
  14. Gary Mathews 2018-01-13

    titanium_mobile: https://github.com/appcelerator/titanium_mobile/pull/9725 ti.map: https://github.com/appcelerator-modules/ti.map/pull/219 ti.map-4.1.1: https://github.com/appcelerator-modules/ti.map/releases/tag/android-4.1.1
  15. Onur Yıldırım 2018-01-18

    Thanks Gary, hope these get merged soon.
  16. Onur Yıldırım 2018-01-30

    Gary, a collaborator requested some changes on GitHub, 17 days ago. Can you please have a look at it?
  17. Michael Gangolf 2018-02-18

    Just about the merge/fix: you could have used the custom SDK with the since Jan 13 since it is linked in the PR (by the build-bot) or even create your 7.0.2 version with the few lines of code or ask in ti-slack for someone to compile it for you. Since it is scheduled for 7.1.0 it is not officially merged.
  18. Onur Yıldırım 2018-02-18

    I could not use non-official releases for the app in production.
  19. Gary Mathews 2018-02-28

    7_1_X: https://github.com/appcelerator/titanium_mobile/pull/9894
  20. Lokesh Choudhary 2018-02-28

    FR Passed. PR's merged.
  21. Lokesh Choudhary 2018-03-14

    Verified the fix in SDK 7.1.0.v20180308150545 & 7.2.0.v20180313125304 downloads map module 4.1.1.
  22. Michael Gangolf 2018-07-10

    I think this PR leads to this error when you try to re-add an existing annotation:
        [WARN]  W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.model.Marker.remove()' on a null object reference
        [WARN]  W/System.err: 	at ti.map.TiUIMapView.addAnnotation(TiUIMapView.java:474)
        [WARN]  W/System.err: 	at ti.map.TiUIMapView.addAnnotations(TiUIMapView.java:489)
        [WARN]  W/System.err: 	at ti.map.TiUIMapView.updateAnnotations(TiUIMapView.java:498)
        [WARN]  W/System.err: 	at ti.map.TiUIMapView.propertyChanged(TiUIMapView.java:288)
        [WARN]  W/System.err: 	at org.appcelerator.kroll.KrollProxy.firePropertyChanged(KrollProxy.java:969)
        [WARN]  W/System.err: 	at org.appcelerator.kroll.KrollProxy.onPropertyChanged(KrollProxy.java:1058)
        [WARN]  W/System.err: 	at org.appcelerator.kroll.runtime.v8.V8Function.nativeInvoke(Native Method)
        [WARN]  W/System.err: 	at org.appcelerator.kroll.runtime.v8.V8Function.callSync(V8Function.java:55)
        [WARN]  W/System.err: 	at org.appcelerator.kroll.runtime.v8.V8Function.call(V8Function.java:41)
        [WARN]  W/System.err: 	at ti.modules.titanium.TitaniumModule$Timer.run(TitaniumModule.java:166)
        [WARN]  W/System.err: 	at android.os.Handler.handleCallback(Handler.java:751)
        [WARN]  W/System.err: 	at android.os.Handler.dispatchMessage(Handler.java:95)
        [WARN]  W/System.err: 	at android.os.Looper.loop(Looper.java:173)
        [WARN]  W/System.err: 	at android.app.ActivityThread.main(ActivityThread.java:6459)
        [WARN]  W/System.err: 	at java.lang.reflect.Method.invoke(Native Method)
        [WARN]  W/System.err: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:938)
        [WARN]  W/System.err: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828)
        
    Example:
        var Map = require('ti.map');
        var win = Titanium.UI.createWindow();
        var mapview = Map.createView({
        	bottom: 0,
        	right: 0,
        	width: Ti.UI.FILL,
        	height: Ti.UI.FILL,
        	rotateEnabled: true,
        	mapType: Map.MUTED_STANDARD_TYPE,
        	showsPointsOfInterest: false,
        	userLocation: true,
        });
        var ann = [];	// store annotations
        
        function setData() {
        	for (var i = 0; i < 10; i++) {
        		ann.push(Map.createAnnotation({
        			title: 'Title',
        			subtitle: 'subtitle',
        			latitude: Math.random() * 10 + 40,
        			longitude: Math.random() * 10,
        		}));
        	}
        	mapview.setAnnotations(ann);
        }
        setData();
        
        
        var btn = Ti.UI.createButton({
        	title: "add again",
        	bottom: 40
        });
        var btn2 = Ti.UI.createButton({
        	title: "add new",
        	bottom: 0
        });
        var btn3 = Ti.UI.createButton({
        	title: "set",
        	bottom: 80
        });
        btn.addEventListener("click", function() {
        	// remove and add existing annotation
        	mapview.removeAllAnnotations();
        	mapview.addAnnotation(ann[0]);
        })
        
        btn2.addEventListener("click", function() {
        	// create new annotation and set it
        	var anno = Map.createAnnotation({
        		title: 'Title',
        		subtitle: 'subtitle',
        		latitude: Math.random() * 10 + 40,
        		longitude: Math.random() * 10,
        	})
        	mapview.setAnnotations([anno]);
        })
        
        btn3.addEventListener("click", function() {
        	// reset existing annotation
        	mapview.setAnnotations([ann[0]]);
        })
        win.add(btn);
        win.add(btn2);
        win.add(btn3);
        win.add(mapview);
        win.open();
        
        
    Only the button "Add new" works. If I add or set an existing icon it will crash. Android 7 (HTC A9) Ti SDK 7.2.0.GA Ti.Map 4.3.0 it has something todo with: https://github.com/appcelerator-modules/ti.map/blob/999bd092c0d41be8384d01271cc32888b64fcb05/android/src/ti/map/AnnotationProxy.java#L96 Here: https://github.com/appcelerator-modules/ti.map/blob/master/android/src/ti/map/TiUIMapView.java#L498 annotation.getTiMarker() returns not-null but tiMarker.getMarker() is null (tiMarker.getMarker().remove();). Still investigating what needs to be fixed

JSON Source