NOTE: I had originally used the Timer class in my example for this post but it seems the Timer class doesn’t follow the normal garbage collection rules as mentioned in BIT-101. Anyway code and description updated below.

So what’s wrong with this code?

package
{
    import flash.display.MovieClip;
    import flash.events.TimerEvent;
    import flash.sensors.Geolocation;

    public class Test extends MovieClip
    {
        public function Test()
        {
            var geo:Geolocation = new Geolocation();
            geo.addEventListener( Event.UPDATE, handleUpdate );
        }

        private function handleUpdate( e :Event ) :void
        {
            trace( "Geolocation update." );
        }
    }
}

I’d imagine many would say that there’s nothing wrong with it. Indeed, if you publish and test this code it will most probably run without a hitch, but that’s really just because Flash’s garbage collector is being kind rather than the code being flawless.

I know what you’re thinking. ‘What the heck are you banging on about Mr Caleb and what has this got to do with garbage collection?’

Well here’s what’s up.

My geo variable is local, meaning that it’ll expire at the end of the function it was declared within. Unfortunately this is bad news for my Geolocation object that I created since it no longer has any references pointing to itself. When an object’s reference count reaches zero it gets marked for deletion by the garbage collector.

In other words, the Geolocation object is in serious danger of being removed from memory even though it is still required.

So why wasn’t it? Garbage collection can have an impact on performance so the Flash runtime only performs garbage collection at scheduled periods or when the player is running low on memory. So in most cases, the chances of your object being garbage collected as soon as its reference count reaches zero are slim.

So how do we guarantee that the Geolocation object doesn’t get garbage collected while it’s still running? Simple, use a member variable. Member variables remember have class scope and willl exist for as long as the class instance they belong to:

package
{
    import flash.display.MovieClip;
    import flash.events.TimerEvent;
    import flash.sensors.Geolocation;

    public class Test extends MovieClip
    {
        private var m_geo:Geolocation;

        public function Test()
        {
            m_geo = new Geolocation();
            m_geo.addEventListener( Event.UPDATE, handleUpdate );
        }

        private function handleUpdate( e :Event) :void
        {
            trace( "Geolocation update." );
        }
    }
}

Sure, you can continue to use local variables and hope to get lucky. But the real problem is that when the code breaks it can be extremely difficult to spot. After all, it might not be immediately obvious that your object has been deleted from memory.

Of course, this issue isn’t specific to Flash’s Geolocation class. Almost any object you create will be scheduled for garbage collection once its reference counter reaches zero. For my example code I could just as easily have used the Accelerometer, Sprite or MovieClip class to illustrate the point.

With Flash Player 10.1 now appearing on handsets and Adobe AIR for Android on the horizon you also run the risk of writing code that breaks easily on mobile. Handsets have limited memory compared to desktop and may perform garbage collection more aggressively. Your luck may just run out.

  1. But doesn’t event listener work as strong reference?

    Wwww
  2. It’s the Timer object that references the listener object, not the other way around.

    So the only reference to the Timer object is from the local variable, which ultimately means that the Timer object will be marked for garbage collection as soon as the local variable expires.

    Christopher (Author)
  3. I’m wondering what actually does reference the timer since some thread (i.e. a root object) must know what timers are running. Oh flash, you cobbled together, zany goon.

    izb
  4. And what if I attach Timer to an object from my function? Seems it will solve the problem.

    If you’re making dozen of different objects with timers (for self-destruction or something), you need to create timers dynamically anyway. :/

    Wwww
  5. Seems like originally using the Timer class to illustrate my point was a bad idea: http://www.bit-101.com/blog/?p=1169. Blog entry now updated to use a different class 🙂

    Christopher (Author)