After reading Alex harui's topic on the modules again... I confirmed what I've remembered to be correct.
I would like to ask one more thing:
"You can use the -compiler.keep-all-type-selectors compiler option on the main application to force the main application to register the default styles for every component in the defaults.css file".
Is this a good practice when developing modular applications ?
I consider -compiler.keep-all-type-selectors to be a last resort, not a good practice. In Flex 4 a module will not be pinned in memory by StyleManager unless you explicitly set styles from the module into the top-level StyleManager. I would look elsewhere for the leak. Does CustomClass have metadata. If a module is the first one to load a class with RemoteClass metadata it will cause the module to be pinned in memory. ResourceBundles are another area to keep an eye on.
Thanks for the reply Darrell, as you can see I've started looking into the unloading modules and profiling topic, as I progress with my modular application.
So I am kinda new in both, although I've read all articles I could find I have some problems so I've created a very simple application example again, so you could easily look into it and hopefully spread some light in my confusion.
http://filip.nedyalkov.net/moduleImageStuck/ view source is enabled so you can confirm test what I will describe here, use it to view the source, or download to profile the results I post here.
The scenario of the example is: On app creation 2 modules are loaded and created via moduleInfo:
<s:Group><mx:Image id="imageLoader" /></s:Group>
HNav.mxml - SkinnableContainer
So with the example provided I've made 3 test cases, where I get different results.
1) The first one is as the example is currently setup to run, which means:
- these 2 imports are NOT included in the main app
//import mx.controls.Image; Image;
//import HNav; HNav;
- both modules are loaded via moduleInfo "load()" only method (moduleFactory is not passed).
Darrell, here what I wonder is: "In Flex 4 a module will not be pinned in memory by StyleManager unless you explicitly set styles from the module into the top-level StyleManager". With this said I should be not having my modules pinned into memory with this setup, right? Or I am missing something? Here is the profiler result for both modules - both FlexModuleFactories remain:
2) In the second test case I included the imports along with the current setup:
import mx.controls.Image; Image;
import HNav; HNav;
The result here was nice, both FlexModuleFactories were gone in the profiler. But the question remains - why do I have to declare in my main app these classes when in Flex 4 the StyleManager shouldn't pin them like in case 1) in memory.
3) I also post here this test case 3 because I find it as an unexpected behavior or bug maybe with the mx:Image class.
Here we still have the imports but instead of "load()" we pass in the moduleFactory: load(null,null,null,moduleFactory);
The result of this is having MyModule's FlexModuleFactory stuck in memory with reference with the StyleManager and MyModule2 is completely gone, so it's ok.
Here is the profiler result:
So the question here along with the idea it could be a bug, is: Should I pass moduleFactory to modules I plan to unload? I wanted to pass moduleFactory instead of declaring same styles for each module.
Darrell I'm kinda stuck on these questions, cause I've found nothing on this in articles, and I tried really hard to put my very complexed project into this simple examples, so I get the methodology and logic of how a dynamic system which constantly loads and unloads modules should be structured.
I really hope you find the time to answer me here till I get this running. I'm sure others will find it useful too. Thanks in advance.
1 person found this helpful
I took a look at the first test case. Just because the StyleManager class is appearing in references in the Profiler does not mean it is causing a leak.
Your example showed two different leaks issues with modules.
1. RemoteClass metadata (compile with -keep and look at calls to flash.net.getClassByAlias() in <moduleName>FlexInit.as). Solve the problem by defining ArrayCollection and ArrayList in the top level program.
import mx.collections.ArrayCollection; ArrayCollection;
import mx.collections.ArrayList; ArrayList;
2. Leaks caused by a Singleton being registered from a module. Solve the problem by defining the Singleton in the top-level application.
import mx.managers.DragManager; DragManager;
It isn't needed to solve the leak by I'd recommend you also define PopUpManager in the top-level application.
Ok so, when I used -keep and looked at the calls to flash.net.getClassByAlias() in <moduleName>FlexInit.as, I saw which classes are the classes. As you explain I defined them in the main application and then what? I mean I deleted the generated folder, build again, I opened the module FlexInit again and nothing was changed. How do I know I fixed something, leaks or whatever...
So it seem I've been looking at this the wrong way, cause till now I've been looking in the profiler and I thought that when the FlexModuleFactory for the module is gone, then I've unloaded it successfully. And when I saw the styles there I thought the module is pinned into memory with that.
So to summarize my questions:
1) How do I know I've unloaded a module successfully without causing any memory leaks?
2) Is it safe to pass moduleFactory when loading modules?
After you define the variables in the main application the main application's generated code will call getClassByAlias(), but the module's will not because the class already is already registered.
1) When the number of instances of the module's moduleFactory goes to zero in the profiler (you need to press the garbage collection button a few times) or you see the "[Unload SWF]" message in the debug console.
2) Yes it is safe. Unless you pass the moduleFactory, styles will not be inherited by the module from the main application.
about the getClassByAlias() I understand now, silly me!
First to ask a few questions about your answers cause I'm afraid I could misinterpretate:
1 - When the number of instances of the module's moduleFactory goes to zero in the profiler (you need to press the garbage collection button a few times) or you see the "[Unload SWF]" message in the debug console.
1) With moduleFactory in the profiler do you mean _Module_mx_core_FlexModuleFactory instances?
2) When module is successfully unloaded does "[Unload SWF]" message always shows? I ask this because in some occasions have 0 instances of the _Module_mx_core_FlexModuleFactory but no ["Unload SWF]" message?
2 - Yes it is safe. Unless you pass the moduleFactory, styles will not be inherited by the module from the main application.
3) Do you mean that if I pass moduleFactory to the module it will inherit styles from the main app and that is not a problem and I will still be able to unload the module?
4) Following your advice I added to the test case 1) you checked:
import mx.managers.DragManager; DragManager;
import mx.managers.PopUpManager; PopUpManager;
I was very surprised to see that _MyModule2_mx_core_FlexModuleFactory was gone in the profiler this time. If you check the above image styles were keeping MyModule and MyModule2 FlexModuleFactrories in the profiler. So this problem got solved. Yupiiiii !
Two question on this matter:
- Why didn't I get ["Unload SWF]" message - question 2) comes from here.
- Why did the other module remain _MyModule_mx_core_FlexModuleFactory (the one with the mx:Image)?
2) The "[Unload SWF]" only appears in the console when using the debugger, not the profiler. You can trigger garbage collection in your application by calling System.gc() (usually two or three times).
3) Yes, you will still be able to unload your module.
That's great !
Ok I think I understand a lot more than before, so the only thing that remains unsolved for me at this point are these 2 questions:
1) question 4 from my previous post
2) you said earlier that having the StyleManager as reference in the profiler in the FlexModuleFactory doesn't mean it's causing a memory leak and after that that if the FlexModuleFactory has 0 instances, only then it's unloaded. I am confused, should I consider my module as unloaded if I have 1 instance with references to the StyleManager or not? Again this is connected to question 4 from my previous post. Should I worry that mx:Image is causing this?
Please when you find the time look into this and get back to me. I think that would be all I'll need for now. Your help is greatly appreciated Thanks Darrell !
4) You will only see the "[Unload SWF]" message when using the debugger, not the profiler.
MyModule_mx_core_FlexModuleFactory may be pinned in memory, that's why there is still one instance in memory. I don't have time to look into the issue in detail but I think it may be a ResourceBundle leak. See this bug for more information (https://bugs.adobe.com/jira/browse/SDK-16613) and my comments on 07/24/09. This problem has been fixed in Flex Hero.
If it is what I think, then the ResourceBundle leak can be fixed by adding this code to your top-level application:
Thank you a lot Darrell, I know you are busy, I've learned a lot of things thanks to you in no time.
Yes you are correct about the issue. It got solved as soon as I added the controls bundle to the main app. I also checked both bug reports about the styles and budles, it's great to see both are fixed for the next release. It's great that now I know where to look in those generated classes for unloading related issues.
With that my problems are solved for now. After this simple example I have to migrate what I've learned into my already big application. So I will try to do on my own see if I could make it work with this knowledge.
I think many people will find this topic here and the answers very usefull, so good luck to them, thank Darrell for that
I will try not to bother you anymore at least for this year I wish you happy holidays, health, luck and all the best