Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-19261] Android: Ti.Network.createHTTPClient memory leak

GitHub Issuen/a
TypeBug
PriorityHigh
StatusOpen
ResolutionUnresolved
Affected Version/sn/a
Fix Version/sn/a
ComponentsAndroid
Labelsandroid, httpclient, leak, memory
ReporterAnders Dahl Pape
AssigneeGary Mathews
Created2015-03-09T08:46:21.000+0000
Updated2018-11-14T19:34:14.000+0000

Description

Using the testcase below objects keeps building up (thus increasing heap size) and never gets released. To test open a new alloy project in titanium and edit tiapp.xml so it's debuggable and can be analyzed in Android Monitor.
<Alloy>
	<Window class="container">
		<Label id="label" onClick="doClick">Hello, World</Label>
	</Window>
</Alloy>
function doClick(e)
{
    Alloy.createController('testHTTP').getView().open();
}
$.index.open();
<Alloy>
	<Window id="container">
		<Label text="test http" onClick="close"></Label>
	</Window>
</Alloy>
var url = "http://www.appcelerator.com";
var xhr = Ti.Network.createHTTPClient();
xhr.onload = function(e)
{
    console.log('succes');
    xhr = null;
};
xhr.onerror = function(e)
{
    console.log('error');
    xhr = null;
};
xhr.open("GET", url);
xhr.send();

function close()
{
    $.container.close();
}

var topView = $.getView();
for (var i=0;i<300;i++)
{
    topView.add(
        $.UI.create('Label',{
        text:'Test label '+i,
        top:5,
        color:'#fff',
        font:{fontSize: '10'}
    })
    );
}
To test open the testHTTP window many times and watch how objects increase. In Android Monitor press "Cause GC" from time to time. Waiting to see if the automatic GC picks it up does not make a difference. The example code is simple but as soon as the page opened gets more complex the number of objects/heap size increases faster and eventually leads to an app crash. Note. I've tested this on my Galaxy S3 with Android 4.3

Comments

  1. Amimul Hossain 2015-04-19

    Hello, We have tested this, Seems to work fine with Ti SDK 3.5.1. and 4.0.0.Beta2, Tested with Android 4.4.4- Note 3
  2. Anders Dahl Pape 2015-07-01

    I'm still seeing the issue using Ti SDK 4.0. Tested in both simulator (4.3) and an S3 (with 4.3) and S4 (with 4.4.2) Furthermore if I use this module i'm seeing a drop in objects left behind: https://github.com/ajwhite/titanium-okhttp plus a nice speed increase. I still think theres something wonky on Android.
  3. Radamantis Torres-Lechuga 2015-07-01

    [~andersdp] we can not replicate, can you please send us exact steps to reproduce the issue and some more info?
  4. Anders Dahl Pape 2015-07-06

    I have added some code to the example above. In the testHTTP.js I have made a loop thats adds 300 labels to the window being opened which makes it clearer that something is left behind when the window closes after the Ti.Network.createHTTPClient has been run. To make it more clear what i'm seeing I have made a youtube video for you. The video has three parts: 1. I open the window 25 times, add a label 300 times and then close the window. 2. I open the window 25 times, add a label 300 times, open the Ti HTTPclient and then close the window. 3. I open the window 25 times, add a label 300 times, open a network connection with the https://github.com/ajwhite/titanium-okhttp Titanium OkHttp module. As the video shows only the Ti HTTPclient leaves a lot of objects behind which never disappears. The video can be seen here: https://www.youtube.com/watch?v=tPpyeVB1Vgc I really hope you are able to see the issue now. I have had another developer try it out and he sees it as well.
  5. Jonas Funk Johannessen 2015-07-21

    Hi guys, any update on this issue? I am seeing this leak as well.
  6. Anders Dahl Pape 2015-08-31

    Any news on this issue?
  7. Tim Poulsen 2015-08-31

    As written, you have a problem with controller caching confusing the situation. Alloy's controllers are CommonJS modules, thus module variables, such as xhr are preserved and reused. Reusing an XHR object is not recommended. Here's a Classic app version:

    app.js

       var win = Titanium.UI.createWindow({
       	title: 'Tab 1',
       	backgroundColor: '#fff'
       });
       var label = Titanium.UI.createLabel({
       	color: '#000',
       	text: 'Click me',
       	textAlign: 'center'
       });
       
       label.addEventListener('click', function () {
       	require('netwin').open({
       		modal: true
       	});
       });
       win.add(label);
       
       win.open();
       

    netwin.js

       var Netwindow = function () {
       	var netwin = Titanium.UI.createWindow({
       		title: 'Tab 1',
       		backgroundColor: '#000'
       	});
       	var label = Titanium.UI.createLabel({
       		color: '#fff',
       		text: 'Click me to close',
       		textAlign: 'center'
       	});
       
       	label.addEventListener('click', function () {
       		netwin.close();
       	});
       	netwin.add(label);
       
       	netwin.addEventListener('open', function () {
       		var xhr = Ti.Network.createHTTPClient(),
       			url = 'http://www.google.com';
       		xhr.onload = function (e) {
       			console.log('success');
       			xhr = null;
       		};
       		xhr.onerror = function (e) {
       			console.log('error');
       			xhr = null;
       		};
       		xhr.open("GET", url);
       		xhr.send();
       	});
       
       	return netwin;
       
       };
       
       module.exports = new Netwindow();
       
    Make sure you have the following in your manifest in tiapp.xml:
       <application android:debuggable="true" />
       
    Following these steps, I don't think I'm seeing a leak. Testing on device, using Monitor's Allocation Tracker tab, I open the app then in Monitor click Start Tracking. In the app, tap "Click Me." In Monitor, in the filter box, enter http, then click Get Allocations and a bunch of objects will be listed. In the app, tap "Click me to close" then click Get Allocations again. I see nothing listed. Repeat as desired, and I still see no objects listed when the child window is closed. This would indicate to me that all HTTP-related objects are being released. In an Alloy app, I would use the open event listener technique as I show in the code above so that all your variables are encapsulated within a function and disposed of at the end of that function's invocation.
  8. Anders Dahl Pape 2015-08-31

    Thanks for your time, Tim! Just a quick reply for now (I'm heading out). Using the exact same code in my example but using the https://github.com/ajwhite/titanium-okhttp module instead of TiHTTP I see no objects left behind. As far as I know the OK http module uses a newer version of the http library. If it was a problem with my code the problem should persist? I'm not saying it's not my coding but I'm just trying to understand.
  9. Tim Poulsen 2015-08-31

    The okhttp module may not have the same troubles with reusing objects like the Titanium HttpClient object has. I'm pretty sure Appc has gotten rid of the Apache HTTP code in the newest versions. You might want to try with one of the newer SDKs.
  10. Anders Dahl Pape 2015-09-01

    Sounds interesting about the dropped apache http code. I'm already on the latest stable AppC SDK - could it be in some beta?
  11. Anders Dahl Pape 2015-09-01

    Found some info in the 4.1 GA release notes. I've been using 4.0 recently. Will test it out to see if something has changed.
  12. Fokke Zandbergen 2015-09-01

    [~andersdp] 5.0 (release this month) will no longer use Apache HTTP and will probably solve this issue.
  13. Anders Dahl Pape 2015-09-02

    Sounds great @Fokke
  14. Jonas Funk Johannessen 2015-09-07

    Haven't tried the 5.0 beta just yet but here is nothing in the release notes for 5.0 that indicate a change in the http code. Is it safe to assume it hasn't been updated, or are the release notes incomplete?
  15. Fokke Zandbergen 2015-09-08

    [~jonasfunk] it has been merged to master before 5.0.0 was branched so it is in 5.0. I will ask for the release notes to reflect that. https://github.com/appcelerator/titanium_mobile/pull/7036
  16. Jonas Funk Johannessen 2015-11-05

    Ran this scenario again with the attached test case. From a baseline of 78.000 objects, using 5.1 beta http-client, Monitor reaches approx. 500.000 objects (422.000 unreleased objects ), while https://github.com/ajwhite/titanium-okhttp module leaves just 100.000 objects (22.000 unreleased objects!). There is obviously still an issue here.

JSON Source