1. 從java端返回String[] 數組。
pcTitle 是字符數組
<s:iterator value="pcTitle" id="pctitle" status="list">
<td align="center" class="weather_title" ><s:property value="pcTitle[${list.index}]"/></td>
</s:iterator>
2.從java端返回List<Object>
<s:iterator value="pcKeyList" id="keyList" status="count">
<s:iterator value="#keyList" id="keyView" status="count">
<s:property value="#keyView.id"/> // keyView是List的Object對象
</s:iterator>
</s:iterator>
3.從java端返回List<List<Object>>
跟2 類似,再嵌套一層循環。
4. if 判斷條件
<s:set name="name" value="<%= "'" + request.getParameter("name") + "'" %>" />
<s:if test="#name == 'Max'">
Max's file here
</s:if>
<s:elseif test="#name == 'Scott'">
Scott's file here
</s:elseif>
<s:else>
Other's file here
</s:else>
1. 被刪除對象在外部的所有引用一定要被刪除干凈才能被系統當成垃圾回收處理掉;
2. 父對象內部的子對象被外部其他對象引用了,會導致此子對象不會被刪除,子對象不會被刪除又會導致了父對象不會被刪除;
3. 如果一個對象中引用了外部對象,當自己被刪除或者不需要使用此引用對象時,一定要記得把此對象的引用設置為null;
4. 本對象刪除不了的原因不一定是自己被引用了,也有可能是自己的孩子被外部引用了,孩子刪不掉導致父親也刪不掉;
5. 除了引用需要刪除外,系統組件或者全局工具、管理類如果提供了卸載方法的就一定要調用刪除內部對象,否則有可能會造成內存泄露和性能損失;
6. 父對象立刻被刪除了不代表子對象就會被刪除或立刻被刪除,可能會在后期被系統自動刪除或第二次移除操作時被刪除;
7. 如果父對象remove了子對象后沒有清除對子對象的引用,子對象一樣是不能被刪除的,父對象也不能被刪除;
8. 注冊的事件如果沒有被移除不影響自定義的強行回收機制,但有可能會影響正常的回收機制,所以最好是做到注冊的事件監聽器都要記得移除干凈。
9. 父對象被刪除了不代表其余子對象都刪除了,找到一種狀態的泄露代碼不等于其他狀態就沒有泄露了,要各模塊各狀態逐個進行測試分析,直到測試任何狀態下都能刪除整個對象為止。
內存泄露舉例:
1. 引用泄露:對子對象的引用,外部對本對象或子對象的引用都需要置null;
2. 系統類泄露:使用了系統類而忘記做刪除操作了,如BindingUtils.bindSetter(),ChangeWatcher.watch()函數時候完畢后需要調用ChangeWatcher.unwatch()函數來清除引用 ,否則使用此函數的對象將不會被刪除; 類似的還有MUSIC,VIDEO,IMAGE,TIMER,EVENT,BINDING等。
3. 效果泄露:當對組件應用效果Effect的時候,當本對象本刪除時需要把本對象和子對象上的Effect動畫停止掉,然后把Effect的target對象置null; 如果不停止掉動畫直接把 Effect置null將不能正常移除對象。
4. SWF泄露:要完全刪除一個SWF要調用它的unload()方法并且把對象置null;
5. 圖片泄露:當Image對象使用完畢后要把source置null;(為測試);
6. 聲音、視頻泄露: 當不需要一個音樂或視頻是需要停止音樂,刪除對象,引用置null;
內存泄露解決方法:
1. 在組件的REMOVED_FROM_STAGE事件回掉中做垃圾處理操作(移除所有對外引用(不管是VO還是組件的都需要刪除),刪除監聽器,調用系統類的清除方法) 先remove再置null, 確保被remove或者removeAll后的對象在外部的引用全部釋放干凈;
2. 利用Flex的性能優化工具Profile來對項目進程進行監控,可知道歷史創建過哪些對象,目前有哪些對象沒有被刪除,創建的數量,占用的內存比例和用量,創建過程等信息;
總結:關鍵還是要做好清除工作,自己設置的引用自己要記得刪除,自己用過的系統類要記得做好回收處理工作。 以上問題解決的好的話不需要自定義強制回收器也有可能被系統正常的自動回收掉。
補:
內存回收機制測試:
通過編寫測試程序發現以下規律,flash內存回收機制的一些特點:
1. 自動內存回收時間不確定。
2. 當一個對象存在被其他對象引用時,這個對象不會被內存回收。
3. 當一個流對象被加載,這個被加載的對象及已經占用了內存。
4. 當一個可視化對象被聲明,但 沒有添加到畫面是占用部分內存,加到displayObject上后,占用全部該對象對象全部內存。
5. 當加載重復對象,例如 加載100個同樣的 XX.swf ,如果僅是加載,完成后沒有引用,那么內存變化規律,波浪型的。如果某個時間內存回收。那么最后留在內存中的應該是大小近似于加載1個 XX.swf (比1個XX.swf 要大些),從此可以推理出,要是不同的東西被加載,那么最后即便是沒有內存漏洞,在一定條件下常用的東西內存中可能也會至少保存每一個不同的東西。經我測試好像是這樣的。(測多了可能還會有新發現呢)
6. 引用的包括
1) 對對象的存儲: 例如 使用一個數組保存 某些對象,那么數組不釋放,對象不可能釋放
2) 對事件的監聽: 例如 監聽過程實際上是使用一個對象保存關鍵字和關鍵字關聯的事件,對事件關鍵字,查找然后找出對應的關聯function。以下是as2代碼。As3 的EventDispatcher功能類似
var btnListener:Object = new Object();
btnListener.click = function() {
trace("haha")
};
bt1.addEventListener("click", btnListener);
使用removerEventer 方法定是要清除掉 處理關鍵字索引和function 的對象。這樣即清除掉了計數引用。
3) 強制回收方式,自動內存回收時間不確定,使用特殊的方法,該方法實際上觸發一個錯誤引起資源回收,使無用的不被計數器引用的都要被回收。(暫時不被使用的,沒有引用的那個被自動回收保留的那個一個回收掉)
方法:
try {
trace("force a GC");
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:Error) {
trace(e.message);
}
}
一個例子 假如 有個loader 請求加載url=xxxx.swf 的地址,然后成功加載 xxxx.swf, 10次 ,每次成功后沒有處理,假設這時候自動回收沒有調用,那么使用強制回收,在debug模式下,會看到回收資源。
[Unload SWF] xxxx.swf ,10個這樣的輸出。
7. 編寫代碼注意:
1) 無用的對象,沒有引用
2) 降低類設計之間的耦合度,注意對象傳遞引用的設計等
3) 單例模式,在合適的時候使用
4) 事件循環嵌套造成多次執行,或事件觸發循環bug。
5) 對象重復加同樣的監聽
根據內存特性制作了資源管理類模塊
monitor XML 文件
1.客戶端根據主配置文件加載 相關模塊配置文件,其中之一模塊就是monitor xml文件
在編譯發布客戶端時,可以不包括此文件,在開發人員使用時可以包括此文件,監視客
戶端運行情況,那么這樣有助于使用更少的類,節省資源。
依賴于XML配置體系的修改,打算客戶端重構后實現。
Resource Monitor 資源監視類
資源監視,主要利用弱引用,監視對象是否存在,對象加載的資源大小可以獲得,同過對象
是否存在來統計該所有對象資源大小總和。
統計過程中需要對資源類型劃分,這里涉及到類型如何劃分,以及改造過程中如何傳遞這
些資源的類型。因為具體改造就是通過一個公用函數獲取資源,那么就需要告訴這個函數,
什么地方(模塊)用,以便統計。
工作量分布 1編寫Resource Monitor類,2修改代碼中所有資源加載處。
有一點需要注意,這次添加Resource Monitor類的方式,在以后重構后,加載調用的函數方
式可能都需要改變,設想通過服務來獲取資源。那么這個服務的名稱等信息自然會得到。
使用方法
weeklyLoader = new Loader();//程序中的loader加載 ,不需要改變
RF.load(weeklyLoader,path,"人物圖片");//添加 RF 為資源管理類,采用靜態方法訪問,path 是資源的url,”人物圖片”是模塊或資源類型的名稱。不需要傳遞回調方法。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/cui55/archive/2008/03/31/2232705.aspx