靜態變量你們再熟悉不過了,原本沒什麼好重複的。事情原由是這樣的,最近測試那邊反應正在作的一個產品老是莫名其妙的顯示不出某些數據,甚至閃退崩潰,仔細查了幾遍發現沒什麼問題,最後百般周折發如今那部測試機上運行的時候纔會出現這中問題。因而各類log,各類斷點調試,最後發現都是報的java.lang.NullPointerException,發現是靜態變量的問題,想一想不至於啊...html
bug緣由,測試妹紙用的那部測試機常年用於測試,副職公用手機,裏面你們裝了各類應用,大概不下50多個應用,雖然手機是1G RAM,可是也經不起這麼造,可用內存極小。調試的時候發現誇張的時候,返回到前一個Activity,後面的立刻就被回收了。雖然看起來是外因,但仍是得改啊。總結:Android手機在可用內存及其小的時候,會回收everything,是everything固然包括static。java
怎麼解決呢,各類求解。Android是用Java開發,其靜態變量的生命週期遵照Java的設計。static 修飾的靜態變量,使用很方便,在不一樣的類和包中均可以使用,在虛擬機中單獨佔用內存,沒錯,這些都是它們的優勢,咱們知道靜態變量是在類被load的時候分配內存的,而且存在於方法區。當類被卸載的時候,靜態變量被銷燬。在PC機的客戶端程序中,一個類被加載和卸載,可簡單的等同於jvm進程的啓動和結束。那麼在Android中呢?用的Dalvik vm也是同樣的。不過Android不太突出的進程概念,因此對靜態變量的生命週期就會感受模糊,這種模糊對於值類型是無所謂的,若是是靜態的對象引用,則與內存回收、內存泄漏這些問題有關,有必要加深研究和理解。靜態變量在類被加載的時候分配內存。類在何時被加載?當咱們啓動一個app的時候,系統會建立一個進程,此進程會加載一個Dalvik VM的實例,而後代碼就運行在DVM之上,類的加載和卸載,垃圾回收等事情都由DVM負責。也就是說在進程啓動的時候,類被加載,靜態變量被分配內存。靜態變量在類被卸載的時候銷燬,類在何時被卸載?在進程結束的時候,通常狀況下,全部的類都是默認的ClassLoader加載的,只要ClassLoader存在,類就不會被卸載,而默認的ClassLoader生命週期是與進程一致的。Android中的進程何時結束,這個是Android對進程和內存管理不一樣於PC的核心——若是資源足夠,Android不會殺掉任何進程,另外一個意思就是進程隨時可能會被殺掉。而Android會在資源夠的時候,重啓被殺掉的進程。也就是說靜態變量的值,若是不作處理,是不可靠的,能夠說內存中的一切都不可靠。若是要可靠,仍是得保存到Nand或SD卡中去,在重啓的時候恢復回來。另外一種狀況就是不能把退出全部Activity等同於進程的退出,因此在用戶點擊圖標啓動應用的時候,之前存放於靜態變量中的值,有可能還存在,所以要視具體狀況給予清空操做。安全
解決方案,兩種思路:app
1、根據Google官方的推薦以及百度到的各位大神的推薦,咱們應該儘可能使用繼承自Application的自定義類,在咱們繼承的類中定義須要全局使用的變量,並經過getApplicationContext()來獲取和保存相關的變量便可。jvm
好比:ide
public class TestApplication extends Application {
private int curIndex;
public int getCurIndex() {
return curIndex;
}
public void setCurIndex(int curIndex) {
this.curIndex = curIndex;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onTerminate() {
super.onTerminate();
}
} 測試
使用方法:this
//保存變量
application.setCurIndex(5);
//獲取變量
application.getCurIndex(); spa
TestApplication application = (TestApplication) this.getApplicationContext();
Application是與應用同時存在的,也就是應用在它就在,並不會被GC給莫名其妙的回收掉,所以,使用此方法更加安全的穩妥。本人最後採用的是這種方法,未發現問題。.net
2、觀點不太同樣,甚至和第一種有點小衝突
Application也是同樣不可靠,Application實際上是一個單例對象,也是放在內存中的,當進程被殺掉,就全清空了,只不過Android系統會幫重建Application,而咱們存放在Application的數據天然就沒有了,仍是得本身處理。靜態引用的對象不會被垃圾回收,只要靜態變量沒有被銷燬也沒有置null,其對象一直被保持引用,也即引用計數不多是0,所以不會被垃圾回收。所以,單例對象在運行時不會被回收。
相關資料:http://blog.csdn.net/ctcwri/article/details/8858414
http://blog.csdn.net/weihan1314/article/details/8033052