Wednesday, July 20, 2011

Out of Memory Error in Flash Builder 4

Out of memory errors are no fun! Perhaps I can help you fix yours?

Problem: You're developing an AIR application with a significant (150+) number of embedded assets and you're using FB4. Eventually, you'll add the straw that breaks the camel's (compiler's) back and you'll start getting:

An internal error occurred during: "Building workspace". Java heap space

Solution: The issue is with FB4's compiler and the way it handles large numbers of [embed]s... The only way around the OOM error is to off load the assets to run time, rather than compile time.

In my project, I created separate swfs for imgs, snd/music, CSVs and loaded them @ run time which contained static embeds. No more OOM! W00t!

Another good idea, you can also bump up the default memory allocations for FB/Eclipse in general. Here's a description on how to do that.

Lastly, here's a quick and dirty AssetMgr class that will load in a swf and give access to its contents. This will get you started on the aforementioned solution. (Much thanks to Ian's response on Stackoverflow for giving me this suggestion!)



package{

import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;


/**
* <p>This Asset Manager class loads a swf and gives access to its embeded class objects.</p>
*
* <p>AUTHOR : Jason Leon</p>
* <p>CREATION DATE : July 21, 2011</p>
*
*/

public class AssetMgr {
private var _appDomains:Array = [];
private static var _instance:AssetMgr;
private var _ready:Boolean = false;
// path to asset lib
private const SWF_PATH:String = "swf/AssetLIB.swf";

public function AssetMgr(){};

/*********************************************************
* retrieve instance
* *****************************/
public static function getInstance():AssetMgr {
return _instance = (_instance ? _instance : new AssetMgr()) as AssetMgr;
}

/*********************************************************
* initialize
* @Desc: must complete before assets are accessed
* *****************************/
public function init () : void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleAssetsLoaded);

var request:URLRequest = new URLRequest(SWF_PATH);
loader.load(request);
}

/*********************************************************
* Handle payload
* @Desc: saves Loader data to _appDomains obj
* *****************************/
private function handleAssetsLoaded (event:Event) : void {
var appDomain:ApplicationDomain = LoaderInfo(event.target).applicationDomain;
_appDomains[SWF_PATH] = appDomain;
_ready = true;
}

/*********************************************************
* Request Assets from saved Loader data
* @Param 1: assetName is the literal name of the asset you want to access
* @Param 2: fileName is the literal name of the loader assets (example: SWF_PATH)
* *****************************/
public function getAsset (assetName:String, fileName:String) : Class {
if (_ready) {
var assetFileAppDomain:ApplicationDomain = ApplicationDomain(_appDomains[fileName]);
var assetClassDefinition:Class = assetFileAppDomain.getDefinition(assetName) as Class;
return assetClassDefinition;
} else {
throw new Error("initialization has not completed");
}
}
}
}


Is this not what you're after? You may also want to look into this thread on adobe's site for your OOM needs... It was not the issue that I ran into but did help narrow it down so I could find my solution.

[NOTE: There is a cap to how many [embed] tags you can include in each swf library you create. I haven't bothered to count to see what the limit is but I've certainly run across it so beware.]

About Me

I produce and engineer games and applications. | Portfolio | LinkedIn