Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-7409] Android: Memory leak for proxies that have no references

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2012-02-14T23:29:03.000+0000
Affected Version/sRelease 1.8.0.1
Fix Version/sSprint 2012-03, Release 2.0.0, Release 1.8.2
ComponentsAndroid
Labelsmodule_memory, qe-testadded
ReporterJosh Roesslein
AssigneeJosh Roesslein
Created2012-01-25T15:54:10.000+0000
Updated2012-12-31T23:35:22.000+0000

Description

*Expected Behavior* When a proxy has no more references from JavaScript or in the platform Java code it should be collected from memory. *Actual Behavior* Proxies never get reclaimed causing the applications heap to grow as proxies are created.

Comments

  1. Josh Roesslein 2012-01-25

    Here is a test case that helps test creating proxies and dereferencing them to simulate the collection process.
       
       var win = Ti.UI.createWindow({
       	title: "Proxy collection test.",
       	backgroundColor: "blue",
       	layout: "vertical"
       });
       
       var parentView = Ti.UI.createView();
       
       var views = [];
       
       var createViews = Ti.UI.createButton({
       	title: 'Create Views'
       });
       createViews.on('click', function () {
       	for (var i = 0; i < 1000; i++) {
       		var view = Ti.UI.createView({backgroundColor:"blue"});
       		views.push(view);
       	}
       });
       win.add(createViews);
       
       var addViewsAsChildren = Ti.UI.createButton({
       	title: 'Add Views as Children'
       });
       addViewsAsChildren.on('click', function () {
       	var count = views.length;
       	for (var i = 0; i < count; i++) {
       		parentView.add(views[i]);
       	}	
       });
       win.add(addViewsAsChildren);
       
       var releaseViews = Ti.UI.createButton({
       	title: 'Release Views'
       });
       releaseViews.on('click', function () {
       	views = [];
       });
       win.add(releaseViews);
       
       var releaseParentView = Ti.UI.createButton({
       	title: "Release Parent View"
       });
       releaseParentView.on('click', function () {
       	parentView = Ti.UI.createView();
       });
       win.add(releaseParentView);
       
       var getChildren = Ti.UI.createButton({
       	title: "Get Children"
       });
       getChildren.on('click', function () {
       	parentView.children.forEach(function (child) {
       		Ti.API.info(child.getHeight());
       	});
       });
       win.add(getChildren);
       
       win.open();
       
  2. Josh Roesslein 2012-01-27

    Here is a test case to verify the Window proxies remain alive until they are closed. Expected: Application should not crash when opening then closing window.
       var mainWindow = Ti.UI.createWindow({
       	title: "main window",
       	backgroundColor: "red"
       });
       
       var openWindowBtn = Ti.UI.createButton({
       	title: "Open Window"
       });
       openWindowBtn.on('click', function () {
       	var newWin = Ti.UI.createWindow({
       		title: "New window",
       		backgroundColor: "blue"
       	});
       
       	var closeBtn = Ti.UI.createButton({
       		title: "Close"
       	});
       	closeBtn.on('click', function () {
       		newWin.close();
       	});
       	newWin.add(closeBtn);
       	
       	newWin.open();
       });
       mainWindow.add(openWindowBtn);
       
       mainWindow.open();
       
  3. Marshall Culpepper 2012-01-27

    To check that this collection is happening correctly, you'll need to: * Make sure android:debuggable="true" is in your application in tiapp.xml: (example, your app ID etc will be different)
       <ti:app>
           <!-- other stuff.. -->
           <android xmlns:android="http://schemas.android.com/apk/res/android">
               <manifest>
                   <application android:icon="@drawable/appicon"
                       android:label="pullRequestSandbox" android:name="PullrequestsandboxApplication"
                       android:debuggable="true">
                   </application>
               </manifest>
           </android>
       </ti:app>
       
    * Open the process w/ DDMS and make sure that Heap collection is enabled, and click "Cause GC" * Click "Create Views" several times in the app to build up the heap size * Click "Release Views", and using DDMS click "Cause GC" a few more times and you should see the memory go back down
  4. Jick Steen 2012-02-01

    Is this fix going to be merged into Mobile SDK 1.8.2 branch?
  5. Neeraj Gupta 2012-02-01

    Yes.
  6. Michael Pettiford 2012-02-07

    Closing issue Tested with Ti Studio build 1.0.8.201201262211 Ti Mob SDK 1.9.0.v20120207124634 OSX Lion 10.7.2 Nexus S OS 2.3.6 Tested against both provided sample codes and the expected results were shown
  7. Markus Krug 2012-02-13

    Hi! Sorry for asking, I'm just wondering. You wrote this will be merged into 1.8.2 Ti Mobile. When is this happening? Before the official 1.8.2 release? Just asking cause I plan to release a new version of my app soon. By the way: I can confirm the fix in 1.9 Ti Mobile is working. Keep up the amazing work!
  8. Neeraj Gupta 2012-02-13

    This fix will be part of 1.8.2 release that is slated to go out by the end of Feb 2012.
  9. Justin Lewis 2012-12-07

    Maybe I'm doing something wrong, but I still see this memory leak on Android using Josh Roesslein's code sample posted 25/Jan/12 1:04 PM. I put that in my app.js, and run. I see the memory go up clicking "Create Views", but clicking "Release Views" never causes the memory use to go down. I've tried compiling against Android SDK 2.2, 3.0, and 4.0, on emulators running the same versions of Android. I've tried several versions of the Titanium SDK as well. I started with 2.1.4, then tried 2.1.5, 1.8.3, 3.0.0 and 3.1.0. I've also tried JDK versions jdk1.7.0_09, and jdk1.6.0_37. This isn't a small leak either, it's about 1MB per click of Create Views. I've seen this in my own app, and my own testing as well. But, I tried the given example to prove to myself that it's not just my poor coding that's the issue.
  10. Allen Yeung 2012-12-10

    I just tried this with 3.1.0, and the test case is working for me. Keep in mind that the 'release views' only removes the references to the view, and there may be a lag on when the VM actually garbage collects the views.
  11. Justin Lewis 2012-12-10

    Thanks for the response Allen. I've found the behavior isn't quite that simple. I originally ran all of these tests in the emulator, always clicking "Release Views" just once. I've since switched to using a physical device. What I see there is, I click "Create Views" and memory usage goes up. I click "Release Views" and memory usage sometimes goes down, and sometimes doesn't. Typically, I need to hit the "Release Views" button many times (between 5 and 10) before the memory usage drops. I've also tried hitting "Release Views" then leaving the phone alone for awhile, in case it just needed time. In those cases, no matter how long I leave the phone alone, up to an hour in a couple of cases, the memory usage still doesn't go down until I hit the "Release Views" button several more times. And as a final test, I also added a "Do Nothing" button that has a click handler, but doesn't do anything. Clicking "Release Views" once, then my "Do Nothing" button continuously has no effect. I have to hit the "Release Views" button several times in most cases to see the memory usage drop. And, I added a print at the end of "Release Views" to verify that views is indeed empty, with length 0 after the first press. However, memory usage does always drop, if I hit "Release Views" enough times. I don't know if this is quirk of Android's garbage collection, or of my 3 Motorola phones, or if there's something else going on that I just don't understand.
  12. Justin Lewis 2012-12-31

    After some more experimenting, taking the Alloy sample book search application, I made a minor modification. I took everything from index, and moved it into book_search. Then I modified index so that it is a modal window with a single button with an OnClick handler that opens the book_search window. Clicking the button, doing a search, the hitting back leaks memory. I've seen it lose as much as 300k at a time. It seems the amount of memory leaked is random, averaging 100k-200k/iteration. But, each search shows an increasing amount of memory usage. I do not see any of these leaks on IOS. I have tried SDK version 3.0.0GA and 3.1.0v201228131005, both show the leak. This has only been tested on my Motorola Droid HD Maxx Android Version 4.1.1

JSON Source