自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android內(nèi)存機(jī)制分析下篇:分析APP內(nèi)存使用情況

移動(dòng)開發(fā) Android
本文主要是分析了如何獲取我們應(yīng)用的內(nèi)存使用情況信息,關(guān)于這方面的信息,其實(shí)還有其他一些方法。另外還介紹APP應(yīng)用的默認(rèn)內(nèi)存已經(jīng)Android的GC回收,不過上面只是很淺薄地分析了一下,讓大家有個(gè)印象。這些東西真要深入分析得花不少精力。因?yàn)槲覀兊哪康闹皇墙鉀QOOM問題,所以目前沒打算深入分析,后面有時(shí)間進(jìn)行Android系統(tǒng)分析的時(shí)候,我們?cè)偕钊敕治觥?/div>

上面一篇文章說了Android應(yīng)用運(yùn)行在dalvik里面分配的堆和棧內(nèi)存區(qū)別,以及程序中什么代碼會(huì)在哪里運(yùn)行。今天主要是講解一下Android里面如何分析我們程序內(nèi)存使用情況。以便后續(xù)可以分析我們程序瓶頸,優(yōu)化方案。

1、APP默認(rèn)分配內(nèi)存大小

在Android里,程序內(nèi)存被分為2部分:native和dalvik,dalvik就是我們普通的java使用內(nèi)存,也就是我們上一篇文章分析堆棧的時(shí)候使用的內(nèi)存。我們創(chuàng)建的對(duì)象是在這里面分配的,對(duì)于內(nèi)存的限制是 native+dalvik 不能超過最大限制。android程序內(nèi)存一般限制在16M,也有的是24M(早期的Android系統(tǒng)G1,就是只有16M)。具體看定制系統(tǒng)的設(shè)置,在Linux初始化代碼里面Init.c,可以查到到默認(rèn)的內(nèi)存大小。有興趣的朋友,可以分析一下虛擬機(jī)啟動(dòng)相關(guān)代碼。這塊比較深入,目前我也沒時(shí)間去分析,后面有空會(huì)去鉆研一下。

  1. gDvm.heapSizeStart = 2 * 1024 * 1024;   // heap初始化大小為2M 
  2. gDvm.heapSizeMax = 16 * 1024 * 1024;    // 最大的heap為16M

2、Android的GC如何回收內(nèi)存

Android的一個(gè)應(yīng)用程序的內(nèi)存泄露對(duì)別的應(yīng)用程序影響不大。為了能夠使得Android應(yīng)用程序安全且快速的運(yùn)行,Android的每個(gè)應(yīng)用程序都會(huì)使用一個(gè)專有的Dalvik虛擬機(jī)實(shí)例來運(yùn)行,它是由Zygote服務(wù)進(jìn)程孵化出來的,也就是說每個(gè)應(yīng)用程序都是在屬于自己的進(jìn)程中運(yùn)行的。Android為不同類型的進(jìn)程分配了不同的內(nèi)存使用上限,如果程序在運(yùn)行過程中出現(xiàn)了內(nèi)存泄漏的而造成應(yīng)用進(jìn)程使用的內(nèi)存超過了這個(gè)上限,則會(huì)被系統(tǒng)視為內(nèi)存泄漏,從而被kill掉,這使得僅僅自己的進(jìn)程被kill掉,而不會(huì)影響其他進(jìn)程(如果是system_process等系統(tǒng)進(jìn)程出問題的話,則會(huì)引起系統(tǒng)重啟)。

做應(yīng)用開發(fā)的時(shí)候,你需要了解系統(tǒng)的GC(垃圾回收)機(jī)制是如何運(yùn)行的,Android里面使用有向圖作為遍歷回收內(nèi)存的機(jī)制。Java將引用關(guān)系考慮為圖的有向邊,有向邊從引用者指向引用對(duì)象。線程對(duì)象可以作為有向圖的起始頂點(diǎn),該圖就是從起始頂點(diǎn)開始的一棵樹,根頂點(diǎn)可以到達(dá)的對(duì)象都是有效對(duì)象,GC不會(huì)回收這些對(duì)象。如果某個(gè)對(duì)象 (連通子圖)與這個(gè)根頂點(diǎn)不可達(dá)(注意,該圖為有向圖),那么我們認(rèn)為這個(gè)(這些)對(duì)象不再被引用,可以被GC回收。

因此對(duì)于我們已經(jīng)不需要使用的對(duì)象,我們可以把它設(shè)置為null,這樣當(dāng)GC運(yùn)行的時(shí)候,就好遍歷到你這個(gè)對(duì)象已經(jīng)沒有引用,會(huì)自動(dòng)把該對(duì)象占用的內(nèi)存回收。我們沒法像C++那樣馬上釋放不需要的內(nèi)存,但是我們可以主動(dòng)告訴系統(tǒng),哪些內(nèi)存可以回收了。

3、查看應(yīng)用內(nèi)存使用情況

下面我們看看如何在開發(fā)過程中查看我們程序運(yùn)行時(shí)內(nèi)存使用情況。我們可以通過ADB的一個(gè)命令查看:

  1. //$package_name:應(yīng)用包名 
  2. //$pid:應(yīng)用進(jìn)程ID,可以用PS命令查看 
  3. adb shell dumpsys meminfo $package_name or $pid 

上面是我使用包名查看Gallery例子的內(nèi)存使用情況圖,里面信息很多,不過我們主要關(guān)注的是native和Davilk的使用情況。(Android2.X和Android4.X查看的信息排序是不一樣的,內(nèi)容差不多,不過排布有差異,我上面是4.0的截圖)

Android底層內(nèi)核是基于Linux的,而Linux里面相對(duì)Window來說,有一點(diǎn)很特別的是,會(huì)盡量使用系統(tǒng)內(nèi)存加載一些緩存數(shù)據(jù)或者進(jìn)程間共享數(shù)據(jù)。Linux本著不用白不用的原則,會(huì)盡量使用系統(tǒng)內(nèi)存,加快我們應(yīng)用的運(yùn)行速度。當(dāng)然,如果我們期待某個(gè)需要大內(nèi)存的應(yīng)用,系統(tǒng)也能馬上釋放出一定的內(nèi)存使用,這是系統(tǒng)內(nèi)部調(diào)度實(shí)現(xiàn)。因此嚴(yán)格來說,我們要準(zhǔn)備計(jì)算Linux下某個(gè)進(jìn)程內(nèi)存大小比較困難。 因?yàn)橛衟aging out to disk(換頁),所以如果你把所有映射到進(jìn)程的內(nèi)存相加,它可能大于你的內(nèi)存的實(shí)際物理大小。

  • dalvik:是指dalvik所使用的內(nèi)存。
  • native:是被native堆使用的內(nèi)存。應(yīng)該指使用C\C++在堆上分配的內(nèi)存。
  • other:是指除dalvik和native使用的內(nèi)存。但是具體是指什么呢?至少包括在C\C++分配的非堆內(nèi)存,比如分配在棧上的內(nèi)存。puzlle!
  • Pss:它是把共享內(nèi)存根據(jù)一定比例分?jǐn)偟焦蚕硭母鱾€(gè)進(jìn)程來計(jì)算所得到進(jìn)程使用內(nèi)存。網(wǎng)上又說是比例分配共享庫占用的內(nèi)存,也就是上面所說的進(jìn)程共享問題。
  • PrivateDirty:它是指非共享的,又不能換頁出去(can not be paged to disk )的內(nèi)存的大小。比如Linux為了提高分配內(nèi)存速度而緩沖的小對(duì)象,即使你的進(jìn)程結(jié)束,該內(nèi)存也不會(huì)釋放掉,它只是又重新回到緩沖中而已。
  • SharedDirty:參照PrivateDirty我認(rèn)為它應(yīng)該是指共享的,又不能換頁出去(can not be paged to disk )的內(nèi)存的大小。比如Linux為了提高分配內(nèi)存速度而緩沖的小對(duì)象,即使所有共享它的進(jìn)程結(jié)束,該內(nèi)存也不會(huì)釋放掉,它只是又重新回到緩沖中而已。

上面針對(duì)meminfo里面的信息給出解析,這些很多我是參考了網(wǎng)上一些文章,所以如果有理解不到位的,歡迎各位指出。

4、程序中獲取內(nèi)存信息

通過ActivityManager獲取相關(guān)信息,下面是一個(gè)例子代碼:

  1. private void displayBriefMemory()  
  2. {     
  3.     final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);     
  4.     ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();    
  5.     activityManager.getMemoryInfo(info);     
  6.   
  7.     Log.i(tag,"系統(tǒng)剩余內(nèi)存:"+(info.availMem >> 10)+"k");    
  8.     Log.i(tag,"系統(tǒng)是否處于低內(nèi)存運(yùn)行:"+info.lowMemory); 
  9.     Log.i(tag,"當(dāng)系統(tǒng)剩余內(nèi)存低于"+info.threshold+"時(shí)就看成低內(nèi)存運(yùn)行"); 

另外通過Debug的getMemoryInfo(Debug.MemoryInfo memoryInfo)可以得到更加詳細(xì)的信息。跟我們?cè)贏DB Shell看到的信息一樣比較詳細(xì)。

5、總結(jié)

今天主要是分析了如何獲取我們應(yīng)用的內(nèi)存使用情況信息,關(guān)于這方面的信息,其實(shí)還有其他一些方法。另外還介紹APP應(yīng)用的默認(rèn)內(nèi)存已經(jīng)Android的GC回收,不過上面只是很淺薄地分析了一下,讓大家有個(gè)印象。這些東西真要深入分析得花不少精力。因?yàn)槲覀兊哪康闹皇墙鉀QOOM問題,所以目前沒打算深入分析,后面有時(shí)間進(jìn)行Android系統(tǒng)分析的時(shí)候,我們?cè)偕钊敕治觥O乱淮挝覀冇靡郧皩懙腉allery例子講解如何避免OOM問題,以及內(nèi)存優(yōu)化方法。

PS:如發(fā)現(xiàn)哪里寫錯(cuò)了,煩請(qǐng)各位留言指出,謝謝!

相關(guān)文章:

Android內(nèi)存機(jī)制分析上篇:了解Android堆和棧

責(zé)任編輯:閆佳明 來源: cnblogs
相關(guān)推薦

2010-06-02 11:06:15

Linux 內(nèi)存監(jiān)控

2017-01-18 21:57:14

2010-02-03 17:16:58

Linux內(nèi)存使用

2017-11-30 18:42:22

PythonCPU腳本分析

2010-06-02 12:47:12

Linux 內(nèi)存監(jiān)控

2014-04-24 16:26:31

UbuntuUbuntu 磁盤Linux基礎(chǔ)

2010-09-26 12:45:29

2020-06-17 14:10:01

Python內(nèi)存程序

2022-09-26 09:44:10

Linux

2009-07-09 18:03:25

tomcatJVM內(nèi)存

2020-02-10 19:50:08

Linux內(nèi)存使用命令

2019-06-24 08:53:01

Bash腳本Linux系統(tǒng)運(yùn)維

2020-02-04 13:50:09

Linux進(jìn)程內(nèi)存使用

2010-10-14 16:10:28

MySQL排序

2023-01-27 15:28:04

開發(fā)Python內(nèi)存

2019-11-27 14:38:41

Windows 10Firefox高CPU

2022-11-11 14:48:41

內(nèi)存top命令

2022-07-13 14:26:26

Linux

2019-09-17 12:13:05

BashLinuxCPU

2011-09-02 10:42:30

linuxfree內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)