性能優化一直是高級Android工程師必問的,這也每每涉及到對Java、JVM、Android運行機制、監控工具使用等全方位的知識點,是很好的面試方向。面試
本篇會圍繞Android與Java的性能優化專項之內存展開並深刻。數據庫
內存是Android運行性能相當重要的一項指標,每一個進程能使用的內存是有限的。不合理的使用內存會致使頻繁的GC、甚至發生OOM,過多GC會致使App卡頓,而內存泄漏或者內存抖動均可以致使OOM,這是沒法接受的。緩存
所以,對於一個合格的高級Android工程師,必須保持對內存的高度敏感性,本文會針對內存提出一系列性能優化手段。性能優化
好比字符串拼接,能夠手動使用StringBuilder,而不是使用"+","+"被編譯器優化後會每次建立StringBuilder對象,形成浪費;函數
並且,尤爲注意在主線程裏不要過多建立對象。由於在GC時會鎖住堆內存,此時請求分配的線程也會被掛起,這顯然會致使主線程的卡頓。因此在一些主線程高頻函數,如onDraw,onTouchEvent裏不要去建立對象。工具
仍是StringBuilder的例子,基於一個StringBuilder能夠經過SetLength(0)
支持不少次的字符串拼接。性能
多使用系統提供的對象池,好比線程池,Long、Integer、Short等包類型裏的緩存值(經過valueOf取),列表view的複用等優化
內存一旦發生泄漏,意味着堆裏有一塊區域持續被再也不使用的變量佔據,這天然會致使可用內存減小而發生gc,甚至OOM。ui
通常內存泄漏有幾下幾種狀況:線程
通常是長生命週期的變量持有Activity引用,致使在gc時沒法標記Activity從而沒法回收,而Activity自己通常會引用到很是多的資源如View, Image,則這些大塊資源均沒法回收。
這種時候,咱們能夠用WeakReference來弱引用;針對Activity這種場景可使用LeakCanary來進行監控,它會在Activity onDestroy後監控其引用是否被釋放,若未釋放則主動觸發一次gc,gc後若是仍未釋放,則會通知開發者。
靜態變量通常是在裝載類裏的連接時進行內存分配,初始化時進行賦值。關鍵是,靜態變量會伴隨Android進程整個生命週期,若是引用了某塊堆內存,則該內存沒法被回收。單例也是相似。咱們在開發中不該該依賴太多靜態變量和單例。
對於一些較大內存的對象,能夠考慮利用finalize方法,防止在忘記釋放時主動進行一些清理工做。像SQLiteDatabase、FileInputStream等都會在finalize方法裏面進行一些清理工做,如關閉數據庫。
不過,finalize方法並非萬能的,它也會致使其餘問題,後續再說。
Java裏提供了四種引用: