什麼是內存
計算機組成:控制器,運算器,存儲器,輸入,輸出
存儲器速度: 寄存器 > x級緩存>內存(主存儲器) ==>RAM(Random Access Memory),掉電後數據丟失
硬盤,ROM,flash是輔存儲器,速度遠慢與內存,屬於外設. ==>速度越快,造價越高
移動設備VS電腦: 而PC即使內存不大,系統通過在外存上創建虛擬內存空間實現內存的"增大".android系統底層雖然使用Linux系統,但是默認是沒有啟用swap分區的.因移動設備普遍內存外存都不夠大,都是窮哥們,沒地兒借.
以上:內存是一種稀缺緊張和珍貴的資源,需要珍惜的使用
Java虛擬機運行時的數據區
<盡請期待>
內存優化:省著用
一些內存的開支情況
任何一個Java類,包括內部類、匿名類,都要占用大概500字節的內存空間
使用枚舉通常會比使用靜態常量要消耗兩倍以上的內存
任何一個類的實例至少消耗16字節的內存開支
在使用HashMap時,即使你只設置了一個基本數據類型的鍵,比如說int,但是也會按照對象的大小來分配內存,大概是32字節,而不是4字節
ArrayList中定義的MIN_CAPACITY_INCREMENT=12, LinkedList每個節點會儲存previous和next節點地址
StringBuider中定義INITIAL_CAPACITY=16, 擴大的算法 int newCount = ((value.length>>1) +value.length) +2
因此,少用枚舉,少創建對象,謹慎選擇和使用集合
使用優化後的數據類型(SparseArray,SparseBooleanArray,SparseIntArray,LongSparseArray)
變量的作用域
局部變量和成員變量
圖片加載
加載到內存的圖片大小不是電腦上看到的大小,而是按照像素計算:
一張1500*1000分辨率照片,使用的ARGB_8888顏色類型,每個像素點佔用4字節內存,總內存就是1500*1000*4字節,總內存就是5.7M
排序算法
<盡請期待>
內存優化:及時釋放
內存是如何釋放的:GC(Garbage Collection)
辣雞(Garbage):待釋放的對象
根(Root):一般指堆內存之外,程序能直接訪問到的對象(靜態/全局變量,Thread-Local的變量)==>看虛擬機的圖
GC算法:
引用計數法(Reference Count)
在每個對象中保存這個對象的引用計數, 引用發生增減時對引用數進行更新, 當引用計數變為0時, 就可以清除了
存在問題:循環引用的對象無法被釋放,多線程存在數據同步的問題
標記-清除算法(mark-sweep)
從根開始把所有被引用的對象用遞歸的方式進行標記,然後回收沒有被標記的對象
存在問題:造成大量的內存碎片,時間與存活對象數和對象總數有關,
複製-收集算法(Copy and Collection)
會將從根開始被引用的對象復制到另外的空間中,然后,再將復制的對象所能夠引用的對象用遞歸的方式不斷復制下去。
存在問題:複製對象的開銷比較大,存活比例比較高的情況下很不利,
分代收集算法
不同的對象的生命週期不同,所以可以採用不同的垃圾收集方式. 劃分:年輕代(新創建對象),年老代(n次回收後才活著),持久代(靜態文件等).
GC時會暫停程序的執行
內存洩漏
原因:動態分配的空間使用完沒有釋放
危害:佔據內存空間,可能導致內存溢出
android中常見的5大內存洩漏
1.單例把持context對象
2.資源未關閉造成的洩漏
3.handler造成的內存洩漏
4.線程造成的洩漏
5.非靜態內部類創建靜態實例
找出洩漏:引入LeakCanary,MAT+