Flex – Event Handlers and Weak References

Did you know defining an event handler on an object in Flex can prevent it or other objects from being garbage collected even after all explicit references to the objects have been removed? If not, then keep reading.

Introduction

Previously, I discussed techniques for freeing up memory on video and images in Flex, but I neglected to include a discussion of event handlers. With the release of ActionScript 3, Adobe added the notion of strong references and weak references. Strong references are those references that, if present, will prevent the object from being garbage collected. The presence of only weak references, on the other hand, will allow an object to be garbage collected. When most developers consider garbage collection, they often consider only strong references, those references they explicitly know about. The age-old wisdom, that if you remove all active (strong) references to an object, it will become eligible for garbage collection, overlooks the fact that the object may have strong references from other objects, created via event handler registration.

Event Handlers are Strong References (by default)

Somewhat surprisingly, and perhaps in a move to preserve older source code, the commonly used method addEventListener() creates a strong reference to the event handler by default. That means even after removing all explicit references to an object, it may never be eligible for garbage collection because other objects have subscribed as listeners to the object. If you have a process that repeatedly creates such objects, you have an uncontrolled memory leak that will eventually crash your program. As an example, consider a screen saver application that displays a new Image or Video on the screen every 30 seconds by creating new display objects and discarding the existing ones. Without considering the event handlers on this application, the memory usage could grow without bound, even if you take proper steps to discard the display objects.

From the Adobe Flex 3 documentation:

One important consequence of this parameter involves working with display objects’ events. Normally, you might expect a display object to be removed from memory when it is removed from the display list. However, if other objects have subscribed as listeners to that display object, with the useWeakReference parameter set to false (the default), the display object will continue to exist in Flash Player’s or AIR’s memory even though it no longer appears on the screen.

Solution #1: Proper deconstructor

The most obvious solution to prevent event handlers from holding objects in memory is to call removeEventListener() on the original object for each event handler on it. The problem is Flex does not provide a listAllEventListeners() method nor a removeAllEventListeners() method in the Event Dispatcher API [Feature Request!], so unless you remembered to save a reference to the event handler when you created it, you’re not going to have much luck removing it. This solution requires you to manage a list of event handlers and their associated types, so each can be discarded at a later time. Also, remember to remove the reference to the event handler in the list, such that the act of maintaining a list of references does not prevent garbage collection.

Solution #2: Declare a weak reference

Maintaining a list of event handlers for every object is a bit cumbersome, so luckily Adobe has added a better solution: declare the reference weak when the event is added to the object. In ActionScript 3, Adobe added an overloaded version of addEventListener() that takes 5 parameters. By setting the 5th parameter (useWeakReference) to be true, the event handler and its associated objects will become eligible for garbage collection if the weak reference event handlers are the only ones left.

For example, let’s say you defined a timer to run for 10 seconds and then stop:

var myTimer:Timer = new Timer(10,0);
myTimer.addEventListener(TimerEvent.TIMER,myTimerHandler);

As the code is written, objects referenced by myTimerHandler cannot be garbage collected, even if the timer was never started. Alternatively, if you add the overloaded parameters to the method ,false,0,true, objects referenced by myTimerHandler can be garbage collected:

var myTimer:Timer = new Timer(10,0);
myTimer.addEventListener(TimerEvent.TIMER,myTimerHandler,false,0,true);

Keep in mind, there are situations when it makes sense to define event handlers using strong references even on temporary objects. Just remember to explicitly remove the event handler if you want to reclaim the allocated memory.

Some developers, though, have made cases that Solution #1 is the only correct solution, and that using weak references is not sufficient for proper memory management.

Conclusion: Refactor your code with overloaded parameters

My suggestion to the reader is search through their code for all occurrences of addEventListener. For each occurrence, decide whether the event handler should live for the life of the application and never be garbage collected, or can be removed before the application completes. If it is the former, and the event handler should live indefinitely for the application, then do nothing. If it is the latter, and the event handler may be discarded at some point, add the parameters ,false,0,true to the event handler creation. This will preserve the existing functionality but allow it to be garbage collected. Keep in mind, though, that the event handler will not be garbage collected if you maintain strong or explicit references to it elsewhere. In the previous example, if you defined myTimerHandler to be a class-level member function, then the event handler would not be eligible for garbage collection with or without the change to the event handler registration.

Error’d: European Edition

I traveled to the UK earlier this month and was greeted by an error screen a day for the first three days of my trip.

Day 1: London Subway Station
Nothing like a 5-foot-tall boot screen to make you feel at home in a foreign country.




Day 2: Cardiff Train Station
Found a Windows BSOD while waiting for the train. And they say Linux dominates the European market!




Day 3: London Bus
Found half-way up the stairs of one of London’s famous double decker public buses.




Bonus: Bed Bath & Beyond
So as not to forget American-based errors, here’s one I came across this morning (live for now). Those without time machines are at a severe disadvantage for this Bed Bath & Beyond rebate offer!


By the way, it was an excellent trip, with or without the BSOD’s following me around Europe!

eclipse 3.6 (helios) – four good, 1 bad feature

Last summer, I wrote “eclipse 3.5 – four good, 1 bad feature“.  A year later and Eclipse 3.6 is out.   I didn’t try it earlier because I was busy with the SCEA part 1 and Core Spring 3 certifications.  While I may not be part of the official blogathon this time, I decided to use the same format as I did last year for Eclipse 3.5.  Another big difference is that I’ve only been using Eclipse 3.6 for a couple days this time.

Getting started

Quick install with favorite plugins:

My Eclipse 3.5 workspace was in a good state so I decided to use it for 3.6 development.  I did make a copy of it in case I wanted to go back to 3.5.  It wasn’t too time consuming to download/install “Eclipse IDE for Java EE Developers”.  The download was 206 MB, so I left that alone for a little while.  I also installed the plugins I use regularly as I wanted them installed before switching to do development in the new workspace.

  1. Sysdeo – For Tomcat with Eclipse.
  2. Ecl emma – For code coverage.
  3. PMD – For static analysis.
  4. Subversive – For Subversion connectivity.

Workspace setup:

None!  That’s right.  My settings were preserved.  Even settings for the plugins.  I was impressed with how smoothly this went.

Features

Favorite feature #1 – Subversive

The Subversive plugin was updated quite extensively with the Helios release train.  I have a lot to say on this so it is a whole other blog post.

Favorite feature #2 –Virtual Folders

Virtual folders are like a folder of shortcuts.  While you can’t put any “real” files under them, you can put other virtual folders and linked resources.  This has potential.  It means I can put related data together even if it lives in disparate places.

Favorite feature #3 – WORKSPACE_LOC

When you create a linked resource, you can define variables.  This has been the case in past releases too.  The difference is that you had to create a variable for the workspace location yourself.  Now it is built in.  Minor, yes.  But nice to not have to do.

Favorite feature #4 – Multiple quickfix

When writing Java code, “quick fix” is a convenient way to clean up your code.  Now if you have multiple instances of the same issue in a class, Eclipse offers to clean them all up at the same time.

And the worst feature

Code formatting. What happened? This used to work intuitively and well in Eclipse 3.4.  Yes 3.4.  You may have noticed it is my exact same pet peeve from Eclipse 3.5.  I was hoping they would fix it in Eclipse 3.6, but no such luck.  At least they introduce something new that bothers me more.

In Java, it gets rid of my careful placed (for readability) whitespace between lines. I checked the preferences and “number of empty lines to preserve” is set to one. HTML is much worse. If I format a bunch of lines containing one <input> per line, Eclipse turns this

<input type="hidden" name="action" value="moveAllSave" />
<input type="hidden" name="module" value="${moduleName}" />
<input type="hidden" name="source_forum_id" value="${sourceForumId}" />
<input type="hidden" name="log_type" value="0" />
<input type="hidden" name="log_description" value="bulk move from admin console">

into this
<input type="hidden" name="action" value="moveAllSave" /> <input
type="hidden" name="module" value="${moduleName}" /> <input
type="hidden" name="source_forum_id" value="${sourceForumId}" /> <input
type="hidden" name="log_type" value="0" /> <input type="hidden"
name="log_description" value="bulk move from admin console">

Huh? That didn’t happen before. I tried setting “never join lines” but it doesn’t take effect for HTML. I guess I’m not relying on the code formatting. Unfortunate as it will slow things down. But yuck. Just look at it.