真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

App的待機(jī)內(nèi)存增長(zhǎng)的原因是什么

這篇文章給大家介紹App的待機(jī)內(nèi)存增長(zhǎng)的原因是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

成都創(chuàng)新互聯(lián)是一家專(zhuān)業(yè)提供淳安企業(yè)網(wǎng)站建設(shè),專(zhuān)注與成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、H5場(chǎng)景定制、小程序制作等業(yè)務(wù)。10年已為淳安眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專(zhuān)業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。

1.新問(wèn)題的進(jìn)一步挖掘

在上一節(jié)里,我們介紹了內(nèi)存測(cè)試的基本流程,講述了如何發(fā)現(xiàn)并處理簡(jiǎn)單的內(nèi)存問(wèn)題。對(duì)于Dalvik Heap部分總結(jié)出了一些常見(jiàn)的問(wèn)題模式,以及如何使用工具識(shí)別和處理這些常見(jiàn)的內(nèi)存問(wèn)題。

當(dāng)簡(jiǎn)單問(wèn)題不再是問(wèn)題的時(shí)候,我們就會(huì)開(kāi)始遇上一些奇怪問(wèn)題了,類(lèi)似于下面這些:

“我們這個(gè)版本引入了一個(gè)挺簡(jiǎn)單的庫(kù),內(nèi)存就漲了2M” “這些代碼只是初始化了幾個(gè)對(duì)象,還沒(méi)有開(kāi)始用呢” “我只是改了一行代碼,沒(méi)有創(chuàng)建新對(duì)象” “我一行代碼都沒(méi)改,怎么會(huì)漲呢”

這次出現(xiàn)的問(wèn)題就是這樣這一類(lèi)問(wèn)題,新版本的Dalvik Heap Pss內(nèi)存出現(xiàn)了2M左右的增長(zhǎng)。但Dalvik Heap Alloc只增長(zhǎng)了273K的情況下。而從Dalvik Heap Free也能看出大部分增長(zhǎng)的內(nèi)存是空閑狀態(tài)的。

經(jīng)過(guò)一段時(shí)間對(duì)問(wèn)題的觀(guān)察,我們有以下幾點(diǎn)發(fā)現(xiàn):

  • 經(jīng)過(guò)較長(zhǎng)時(shí)間待機(jī)后也沒(méi)有被釋放回系統(tǒng)。

  • 有幾處代碼會(huì)導(dǎo)致內(nèi)存增長(zhǎng),只要將這些代碼屏蔽掉,內(nèi)存情況就下降到正常水品。

  • 這些代碼分配的內(nèi)存并不多,甚至有些地方是不需要分配內(nèi)存的。

  • 有些代碼并不是這個(gè)版本新加入的,已經(jīng)存在較長(zhǎng)時(shí)間了。

  • 使用裁剪功能的方法編譯并分析內(nèi)存后,基本可以確定是新加入代碼消耗了內(nèi)存,但并沒(méi)有內(nèi)存泄漏,代碼經(jīng)過(guò)review也沒(méi)有發(fā)現(xiàn)問(wèn)題。

這個(gè)結(jié)果讓我們陷入了困惑,常用的方法找不出問(wèn)題,說(shuō)明有更深層次的原因。接下來(lái)要從更底層的Dalvik虛擬機(jī)尋找問(wèn)題。

1.1 Dalvik Heap內(nèi)部機(jī)制

為了弄清楚為什么DVM占著內(nèi)存不釋放,我們閱讀了DVM分配內(nèi)存部分的代碼。位置在Android源碼的dalvik/vm/alloc下,約255K。分析出的主要流程如下:

1)DVM使用mmap系統(tǒng)調(diào)用從系統(tǒng)分配大塊內(nèi)存作為Java Heap。根據(jù)系統(tǒng)機(jī)制,如果分類(lèi)的內(nèi)存尚未真正使用,就不計(jì)入PrivateDirty和PSS。例如圖1-8,Heap Size/Alloc很多,但大部分是共享,實(shí)際使用的較少。所以反映到PrivateDirty/PSS里的內(nèi)存并不多。

圖1-8 共享內(nèi)存較多的進(jìn)程

2)New對(duì)象之后,由于要向?qū)?yīng)的地址寫(xiě)入數(shù)據(jù),內(nèi)核開(kāi)始真正分配該地址對(duì)應(yīng)的4K物理內(nèi)存頁(yè)面。

Alloc.cpp, 176行起:

3)運(yùn)行一段時(shí)間后,開(kāi)始GC,有些對(duì)象被回收了,有些會(huì)一直存在。

4)在GC時(shí),有可能會(huì)進(jìn)行trim。即將空閑的物理頁(yè)面釋放回系統(tǒng),表現(xiàn)為PrivateDirty/PSS下降。

HeapSource.cpp, 431行:

1.2 問(wèn)題所在

在了解DVM分配釋放內(nèi)存的機(jī)制后,根據(jù)dumpsys觀(guān)察到的現(xiàn)象,猜測(cè)可能出現(xiàn)了頁(yè)利用率問(wèn)題(頁(yè)內(nèi)碎片)。如圖1-13所示,第一行:在開(kāi)始階段,內(nèi)存分配的較滿(mǎn)。第二行:經(jīng)過(guò)GC后,大部分對(duì)象被釋放,少部分留下來(lái)。

這種情況下可能會(huì)產(chǎn)生的問(wèn)題是,整頁(yè)的4K內(nèi)存中可能只有一個(gè)小對(duì)象,但統(tǒng)計(jì)PrivateDirty/PSS時(shí)還是按4K計(jì)算。

在通常的jvm虛擬機(jī)中,有Compacting GC機(jī)制,整理內(nèi)存對(duì)象,將散布的內(nèi)存移動(dòng)到一起。但根據(jù)DVM的代碼,DVM的Mark-Sweep算法不能移動(dòng)對(duì)象,即沒(méi)有內(nèi)存整理功能,這種情況下就會(huì)形成內(nèi)存空洞。

在猜測(cè)了可能的問(wèn)題后,需要驗(yàn)證是否如猜測(cè)原因所致,由于MAT的對(duì)象實(shí)例數(shù)據(jù)中有地址和大小信息,我們先從MAT中導(dǎo)出數(shù)據(jù)。

在MAT中列出所有對(duì)象實(shí)例:list_objects java.*,然后選中所有數(shù)據(jù)導(dǎo)出為CSV格式,如下所示:

Class Name,Shallow Heap,Retained Heap,
class java.lang.Class @ 0x41fdd1e8,16,56,
class test.bxi$3 @ 0x432501c8,0,0,
class test.aaw$c$1 @ 0x4324fef8,0,0,
class test.ds @ 0x4324fc88,8,48,
class test.bxh @ 0x4324f438,8,248,
class test.bxg @ 0x4324f248,0,0,
class test.bxd$1 @ 0x4324f028,0,0,

處理導(dǎo)出的csv文件,按頁(yè)面進(jìn)行統(tǒng)計(jì),取每個(gè)對(duì)象的地址的高位(&0xfffff000),結(jié)果相同的對(duì)象處在同一頁(yè)面中。最后再按每個(gè)頁(yè)面所有對(duì)象的大小分類(lèi)統(tǒng)計(jì),做出直方圖如圖1-14所示。

這張圖就是被測(cè)應(yīng)用的頁(yè)面利用率分布圖,左邊是利用率低的頁(yè)面,右邊是利用率高的頁(yè)面。如果發(fā)現(xiàn)利用率低的頁(yè)面數(shù)目增加,說(shuō)明小對(duì)象碎片的數(shù)量增加了。

1.3 優(yōu)化Dalvik內(nèi)存碎片

為了能夠找出有問(wèn)題的代碼,我們將上一步得到的數(shù)據(jù)繼續(xù)處理。取出所有使用不滿(mǎn)2K的頁(yè)面的內(nèi)存塊地址,再使用OQL將地址導(dǎo)入到MAT中,分析地址對(duì)應(yīng)的對(duì)象是什么。如圖1-15所示就是將地址重新導(dǎo)入到MAT中得到的對(duì)象列表了:

在這里基本就能看出來(lái)是哪些對(duì)象造成了內(nèi)存的碎片化,數(shù)量比較多的前幾個(gè)類(lèi)的自然嫌疑比較大,可以先對(duì)前幾個(gè)類(lèi)的相關(guān)代碼進(jìn)行分析。也可以對(duì)這些代碼進(jìn)行針對(duì)性的內(nèi)存測(cè)試,觀(guān)察內(nèi)存情況。

通過(guò)對(duì)生成這些對(duì)象的代碼分析和模擬實(shí)驗(yàn),我們還原出問(wèn)題的基本過(guò)程:

  • 生成對(duì)象過(guò)程需要較多的臨時(shí)變量。

  • 批量生成過(guò)程中,由于還有空閑內(nèi)存,虛擬機(jī)沒(méi)有做GC。

  • 完成后才進(jìn)行GC,清除了所有的零時(shí)變量,留下碎片化的內(nèi)存。

下圖是造成這個(gè)問(wèn)題的類(lèi)似代碼,執(zhí)行這段代碼將會(huì)在內(nèi)存中形成很多碎片,造成很高的PSS占用。

private Object result[] = new Object[100];
void foo() {
  for(int i = 0; i < 100; ++i) {
    byte[] tmp = new byte[2000];
    result[i] = new byte[4];
  }
}

顯示了類(lèi)似情況下數(shù)組的分配范圍,可見(jiàn)數(shù)組中每個(gè)成員的內(nèi)存地址都是不連續(xù)的,并且相隔很遠(yuǎn)。這種情況下就會(huì)消耗很多個(gè)物理內(nèi)存頁(yè)面,增加Heap Free,造成例子中的問(wèn)題。

根據(jù)上述的流程,我們搞清楚了造成問(wèn)題的原因,并且找到了問(wèn)題代碼。那么應(yīng)當(dāng)總結(jié)一些經(jīng)驗(yàn),以供借鑒。對(duì)于測(cè)試人員來(lái)說(shuō),有以下兩個(gè)經(jīng)驗(yàn):

  • MAT是探索Java堆并發(fā)現(xiàn)問(wèn)題的好幫手,能夠迅速發(fā)現(xiàn)常見(jiàn)的圖片和大數(shù)組等問(wèn)題。但僅靠MAT提供的功能也不是萬(wàn)能的,比如這個(gè)問(wèn)題的數(shù)據(jù)就隱藏在對(duì)象的地址中。

  • 對(duì)Android測(cè)試經(jīng)驗(yàn)來(lái)說(shuō),可能容易找到的是應(yīng)用代碼及框架的各種測(cè)試經(jīng)驗(yàn)和指導(dǎo),底層以及涉及性能的測(cè)試經(jīng)驗(yàn)并不太多。這方面可以借鑒Linux系統(tǒng)的測(cè)試經(jīng)驗(yàn),了解內(nèi)核及進(jìn)程相關(guān)的知識(shí),熟悉常用工具。

  • 內(nèi)存分配的最小單位是頁(yè)面,通常為4K。

對(duì)于開(kāi)發(fā)人員,以下兩個(gè)經(jīng)驗(yàn)也許能有幫助:

  • 盡量不要在循環(huán)中創(chuàng)建很多臨時(shí)變量。

  • 可以將大型的循環(huán)拆散,分段或者按需執(zhí)行。

關(guān)于App的待機(jī)內(nèi)存增長(zhǎng)的原因是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。


文章題目:App的待機(jī)內(nèi)存增長(zhǎng)的原因是什么
本文鏈接:http://weahome.cn/article/gegcoc.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部