Android進程管理機制和內存機制



Android進程管理機制和內存機制




我們有時候在開發項目的時候,會一個不小心造成OOM錯誤,相信很多人都知道這個錯誤,這個錯誤是指內存溢出,爲什麼會出現這個錯誤?以及我們在開發之中如何儘量的避免這個錯誤,現在就來聊聊


Android手機系統

我們要知道爲什麼造成OOM,務必來看看Android系統的一些知識

我們使用Android手機的同學應該都知道,手機越用越卡,而且時不時就會出現內存不足的情況,爲什麼呢?原因有以下:

1,我們知道Android是由Java語言編寫,那麼熟悉Java的同學應該知道,Java是運行在虛擬機上的,而不是像蘋果直接運行在系統上,虛擬機不僅非常耗性能,更是垃圾場,隨着時間越來越久,垃圾越來越多,內存就會越來越不足

2,熟悉Android的同學知道,我們app是可以長時間運行在後臺的,不像蘋果,當用戶不用這個app的時候,過了一會系統就殺死了這個app了,既然Android的app是可以長時間運行在後臺,那麼就會不斷的佔用內存和進程,特別是些大型的app,更是消耗很大

3,現在有很多app沒有按照Android的規格去開發,沒有在意app的性能優化,導致app越來越大,消耗的性能也越來越多,在按照上述第2點,結果可想而知

4,熟悉Java的同學應該知道,Java有非常強大的GC機制,可以回收一些沒必要的對象來保證內存的分配,但是,Java的虛擬機卻不能做到隨用隨放,也就是說,當我們內存不足的情況下,它纔可能回收,但是卻不會預先回收垃圾來爲我們的app分配足夠大的內存,在按照上述第1點,也很容易知道結果

5,手機配置不高(除非你換iphone,否則還是逃不過Android系統機制)

上述就是Android系統的一些特性,但是還不夠,我們從進程機制來分析


進程機制和內存機制

我們知道了app是運行在虛擬機上,Android爲每一個app都單獨分配了一個虛擬機,也就是說每個app都有自己的進程,每個進程都有自己的內存空間,這樣做的好處就是當我們當前的app出現問題的時候,系統僅僅殺死當前進程,不會導致其他的app受到牽連,回收之後釋放出內存給其他app使用,進程從高到底分爲5種:

前臺進程

正在與用戶交互的進程,通俗來講就是你當前使用app的進程

可見進程

可以被用戶看到,但是沒有和用戶交互,例如一個activity以對話框的形式覆蓋在當前activity上面,當前activity可以被用戶看到,但是不和用戶交互

服務進程

這個相信大家都熟悉,也就是我們常說的service,能夠運行在後臺,常見的有音樂類的app

後臺進程

注意,這個後臺進程不要和服務進程搞混了,它的意思是說當前app在後臺運行,例如我啓動了app,然後點擊home返回到桌面,那麼這個app就會被切回到後臺進程

空進程

空進程指的是在這些進程內部,沒有任何東西在運行。保留這種進程的的唯一目的是用作緩存,以縮短該應用下次在其中運行組件所需的啓動時間

當我們內存不足資源緊缺的時候,會從低到高去分別釋放進程,從而使app有足夠的內存運行,Android設備出廠以後,java虛擬機對單個應用的最大內存分配就確定下來了,超出這個值就會OOM,不同的設備會有不同的內存空間,所以啊,買Android手機的朋友,最好選配置好一點的,不然卡死你,並且如果多app運行在後臺的話,也會增加流量消耗

其實Android的這種機制有利也有弊,弊我想大家都知道了,那利是什麼呢?不知道大家發現一個問題沒,上述說了Android和蘋果的機制不同,蘋果是會殺死進程,也就是說我重新打開這個app的時候,是需要重新去鏈接網絡獲取信息的,這樣對有些用戶來說也挺煩的,如果我在玩遊戲,突然來消息了,我切換出去久了再切換回來,我又重新來到登錄界面了,我就挺煩這個的,但是Android如果內存足夠,就不需要重新登錄了,另外,Android的app從後臺切換到前臺時,由於系統沒有殺死app,界面是不需要重新讀取,啓動速度會加快,也挺人性化的


內存泄漏

我們瞭解了內存機制之後,我們來看看內存泄漏,內存泄漏通俗一點講就是應該被釋放的資源,因爲某些原因而沒有被釋放掉,爲什麼會這樣呢?我們需要簡單瞭解下Java的垃圾回收機制(GC)

GC機制

我們在開發過程中,少不了對象的創建,我們所創建的對象都是存儲在Java虛擬機的內存之中,我們並不用去關心對象的釋放,因爲這一切都是由GC幫我們去完成,但是,這是有條件的

1,無用對象

2,內存不足

無用對象簡單概括就是,我們創建出一個對象的時候,但並沒有對這個對象賦值或者說沒用到這個對象,另外一種,這個對象已經使用完了,不會再被其他程序調用,舉個例子,我們使用I/O流的時候,我們使用完了之後都需要釋放掉,因爲我們使用完之後已經沒用其他程序在去調用了,那麼這個對象應當屬於無用對象

當內存空間出現緊缺,Java會回收一些進程來確保內存空間,我們知道我們每一個app都是有單獨的進程,回收進程的時候,也就是將我們的對象資源進行回收,也就是將我們無用對象進行回收

但是,如果在一個進程當中,對象已經用完了,但是因爲某些原因與其他資源捆綁住,GC回認爲這個對象可能還需要被其他程序調用,但是實際上沒有程序再去調用它,那麼就會導致這個對象一直在佔用着內存,另外一種,如果兩個無用對象相互牽引着,也會導致GC無法回收,內存一直會被佔用,就會導致了內存泄漏,舉幾個例子:

1,廣播在Activity銷燬的時候沒有釋放掉:因爲廣播持有Activity對象,當Activity銷燬時,GC去回收它的對象,但是這時候,我們沒有釋放廣播,所以它沒辦法去回收,就會導致內存泄漏

2,Handler做耗時操作:如果我們在Handler中做比較耗時的操作,在這個操作還沒有完成的時候,我們銷燬Activity,Handler應當是個無用對象,但是它卻賴着不走,GC也無法強制把它帶走,也會造成內存泄漏

3,非靜態內部類的靜態調用:我們在Activity中定義一個內部類,然後以靜態的方式去引用它,我們知道靜態的特性是唯一性,也就是說這個被定義爲靜態的對象的生命週期是和app生命週期一樣長,但是我們的內部類是非靜態的,是依附在當前Activity的生命週期上的,當Activity被回收後,因爲內部類的對象持有Activity對象,而且它的生命週期是app的生命週期,所以會導致Activity沒辦法被正常回收

.。。。

還有很多其他的例子,就不一一列舉了,現在大概瞭解什麼是內存泄漏以及內存泄漏造成的原因了吧


內存溢出

內存泄漏會造成內存無法被釋放,系統無法爲其他一些app開闢更多的內存空間,當我們內存泄漏越來越大的時候,已經超出我們正常內存空間的時候,就是我們常說的內存溢出

相信大家對內存泄漏和內存溢出的危害都有一定的瞭解,它可以讓我們手機越來越卡,嚴重的會造成系統崩潰,舉個很通俗的例子,我們往袋子中注入水,當越來越多的時候,水會溢出來,並且嚴重的時候袋子會裂開,所以,不要小看內存溢出,小的內存溢出可能我們感覺不到,但是積少成多,終究會發生問題

這也就是爲什麼我們手機系統會越來越卡,也是我們爲什麼Android系統會崩潰的原因,我們來簡單總結下:

1,app都有自己單獨的進程,每臺設備在出廠的時候都會設定了我們單個app所佔用的內存

2,app運行在後臺時,當系統內存不足的時候,會根據進程的級別高低去回收進程

3,當我們對象資源無法被回收的時候,會造成內存泄漏,如果app的內存泄漏過多,超過內存空間,就會造成內存溢出

4,內存泄漏和內存溢出會造成手機系統越來越卡,嚴重的會導致系統崩潰

5,在實際開發之中,我們要嚴格按照Android的規範來編寫程序,避免內存泄漏內存溢出等問題發生

好了,這篇文章就到這~~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章