- GC_EXTERNAL_ALLOC:這是為external分配的內存執行的GC,也就是上文提到的Bitmap Pixel Data之類的。
- GC_HPROF_DUMP_HEAP:這是當你做HPROF這樣一個操作去創建一個HPROF profile的時候執行的。
- GC_EXPLICIT:這是由于你顯式的調用了System.gc(),這是不提倡的,一般來說我們可以信任系統的GC。
freed 2049K表明在這次GC中回收了多少內存。
65% free 3571K/9991K是heap的一些統計數據,表明這次回收后65%的heap可用,存活的對象大小3571K,heap大小是9991K。
external 4703K/5261K是Native Memory的數據。放Bitmap Pixel Data或者是NIO Direct Buffer之類的。第一個數字表明Native Memory中已分配了多少內存,第二個值有點類似一個浮動的閥值,表明分配內存達到這個值系統就會觸發一次GC進行內存回收。
paused 2ms 2ms表明GC暫停的時間。從這里你可以看到越大的heap size你需要暫停的時間越長。如果是concurrent gc你會看到2個時間一個開始一個結束,這時間是很短的,但如果是其他類型的GC,你很可能只會看到一個時間,而這個時間是相對比較長的。
通過Log可以對內存信息有個基本的了解,但這不足以了解什么對象在使用內存,在哪使用了內存。這時候你需要用Heap Dumps。一個Heap Dump基本上來說就是一個包含你heap中所有對象信息的二進制文件。你可以用DDMS來生成這個文件,點擊DDMS中下圖的那個按鈕。
同時Heap Dumps也有對應的API,你想要在特定的時間點獲取一份Heap Dump,使用android.os.Debug.dumpHprofData()。獲取到的文件要轉換成標準的HPROF格式,使用如下命令:hprof-conv orig.hprof converted.hprof。然后用MAT或者jhat進行分析。
在講MAT之前先講下Memory Leaks。要清楚GC并不能防止Memory Leaks,所謂Memory Leaks就是引用到了已經沒用的對象從而讓這些對象避免了被GC回收,跟C/C++中的概念并不一樣。容易導致內存泄漏的是一些Activity,Context,View,Drawable之類的引用,和一些非靜態的內部類比方說Runnable之類的以及一些Caches。比如你旋轉屏幕的時候在新的方向上產生一個新的Activity,如果有變量引用到舊的Activity就會導致其無法被GC,造成Memory Leaks。
通常通過上面介紹的Log信息,只要已用memory一直處于上升的情形而不回落,便大致能了解到應用存在Memory Leaks。不過MAT這類工具可以幫助你更好的對memory進行分析。使用MAT之前有2個概念是要掌握的:Shallow heap和Retained heap。Shallow heap表示對象本身所占內存大小,一個內存大小100bytes的對象Shallow heap就是100bytes。Retained heap表示通過回收這一個對象總共能回收的內存,比方說一個100bytes的對象還直接或者間接地持有了另外3個100bytes的對象引用,回收這個對象的時候如果另外3個對象沒有其他引用也能被回收掉的時候,Retained heap就是400bytes。
MAT使用Dominator Tree這樣一種來自圖形理論的概念。
所謂Dominator,就是Flow Graph中從源節點出發到某個節點的的必經節點。那么根據這個概念我們可以從上圖左側的Flow Graph構造出右側的Dominator Tree。這樣一來很容易就看出每個節點的Retained heap了。Shallow heap和Retained heap在MAT中是非常有用的概念,用于內存泄漏的分析。
我們用Honeycomb3.0中的HoneycombGallery做一個Demo。在工程的MainActivity當中加入如下代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class MainActivity extends Activity implements ActionBar.TabListener {
static Leaky leak = null;
class Leaky {
void doSomething() {
System.out.println("Wheee!!!");
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (leak == null) {
leak = new Leaky();
}
...
|
原文轉自:http://my.eoe.cn/futurexiong/archive/1299.html