Android應(yīng)用開發(fā)中l(wèi)argeHeap屬性的妙用與潛在風(fēng)險(xiǎn)
largeHeap是Android開發(fā)中的一個(gè)屬性,主要作用是向系統(tǒng)請求為App進(jìn)程的虛擬機(jī)分配更大的堆內(nèi)存空間。在manifest文件的application節(jié)點(diǎn)或activity節(jié)點(diǎn)中使用。largeHeap屬性設(shè)置為true時(shí),應(yīng)用可以使用更大的堆內(nèi)存。具體能為虛擬機(jī)分配多大的堆內(nèi)存,取決于當(dāng)前設(shè)備的相關(guān)配置,由dalvik.vm.heapsize后面的配置大小限制。
在Android開發(fā)中,官方建議開發(fā)者應(yīng)努力減少內(nèi)存的使用,采用回收和復(fù)用的方法,而不是通過增大內(nèi)存來解決內(nèi)存問題。當(dāng)內(nèi)存過大時(shí),每次垃圾回收(gc)的時(shí)間也會(huì)變長,可能導(dǎo)致性能下降。
largeHeap具體分配大小
largeHeap屬性本身并不直接指定一個(gè)具體的內(nèi)存大小。實(shí)際可以看做是一個(gè)用于向系統(tǒng)請求為應(yīng)用進(jìn)程分配更大的堆內(nèi)存空間標(biāo)志。具體能為虛擬機(jī)分配多大的堆內(nèi)存,取決于當(dāng)前設(shè)備的配置和系統(tǒng)的內(nèi)存管理策略。
在Android設(shè)備中,每個(gè)應(yīng)用都會(huì)有一個(gè)內(nèi)存最大值的限制。在應(yīng)用的manifest文件中為某個(gè)activity或整個(gè)應(yīng)用設(shè)置了largeHeap="true"后,這個(gè)應(yīng)用或activity可以嘗試使用比默認(rèn)限制更大的堆內(nèi)存?!案蟆钡亩褍?nèi)存具體有多大,并不是固定的,受到設(shè)備總內(nèi)存、其他應(yīng)用和系統(tǒng)服務(wù)的內(nèi)存需求,以及Android版本和廠商定制等因素的影響。
獲取當(dāng)前應(yīng)用可以使用的最大堆內(nèi)存大小方法:
//如果largeHeap屬性被設(shè)置為true,將返回一個(gè)比默認(rèn)情況下更大的值。
Runtime.getRuntime().maxMemory()
//獲得應(yīng)用正常情況下內(nèi)存的大小
ActivityManager.getMemoryClass();
//獲得開啟largeHeap最大的內(nèi)存大小
ActivityManager.getLargeMemoryClass();
在/system/build.prop文件中,可以找到與內(nèi)存管理相關(guān)的設(shè)置,如dalvik.vm.heapsize和dalvik.vm.heapgrowthlimit。定義了應(yīng)用進(jìn)程堆內(nèi)存的默認(rèn)大小和增長限制。
通過adb shell查看:
cat /system/build.prop
圖片
- 「dalvik.vm.heapstartsize=8m」 相當(dāng)于Java虛擬機(jī)的-Xms配置,用來設(shè)置堆內(nèi)存的初始大小。
- 「dalvik.vm.heapgrowthlimit=192m」 相當(dāng)于虛擬機(jī)的-XX:HeapGrowthLimit配置,用來設(shè)置一個(gè)標(biāo)準(zhǔn)的應(yīng)用的最大堆內(nèi)存大小。一個(gè)標(biāo)準(zhǔn)的應(yīng)用就是沒有使用android:largeHeap屬性的應(yīng)用。
- 「dalvik.vm.heapsize=512m」 相當(dāng)于虛擬機(jī)的-Xmx配置,設(shè)置了使用android:largeHeap的應(yīng)用的最大堆內(nèi)存大小。
- 「dalvik.vm.heaptargetutilizatinotallow=0.75」 相當(dāng)于虛擬機(jī)的-XX:HeapTargetUtilization,用來設(shè)置當(dāng)前理想的堆內(nèi)存利用率。取值位于0與1之間,當(dāng)GC進(jìn)行完垃圾回收之后,Dalvik的堆內(nèi)存會(huì)進(jìn)行相應(yīng)的調(diào)整,通常結(jié)果是當(dāng)前存活的對象的大小與堆內(nèi)存大小做除法,得到的值為這個(gè)選項(xiàng)的設(shè)置,即這里的0.75。注意,這只是一個(gè)參考值,Dalvik虛擬機(jī)也可以忽略此設(shè)置。
- 「dalvik.vm.heapminfree=2m與dalvik.vm.heapmaxfree=8m」 前者對應(yīng)的是-XX:HeapMinFree配置,用來設(shè)置單次堆內(nèi)存調(diào)整的最小值。后者對應(yīng)的是-XX:HeapMaxFree配置,用來設(shè)置單次堆內(nèi)存調(diào)整的最大值。通常情況下,還需要結(jié)合上面的-XX:HeapTargetUtilization的值,才能確定內(nèi)存調(diào)整時(shí),需要調(diào)整的大小。
使用largeHeap屬性弊端
largeHeap會(huì)增加應(yīng)用的內(nèi)存使用。雖然可以幫助解決某些OutOfMemoryError(OOM)的問題,但也可能導(dǎo)致系統(tǒng)垃圾回收(GC)的時(shí)間變長。垃圾回收是Android系統(tǒng)用于清理不再使用的內(nèi)存的過程,當(dāng)堆內(nèi)存變得更大時(shí),這個(gè)過程可能需要更長的時(shí)間??赡軐?dǎo)致應(yīng)用在執(zhí)行某些任務(wù)時(shí)變得卡頓,尤其是在進(jìn)行復(fù)雜的UI操作時(shí),如RecyclerView的滑動(dòng)可能會(huì)變得異常緩慢。
過度使用largeHeap可能會(huì)對整個(gè)系統(tǒng)的性能產(chǎn)生負(fù)面影響。如果每個(gè)應(yīng)用都請求更多的內(nèi)存,那么系統(tǒng)可用的總內(nèi)存就會(huì)減少??赡軐?dǎo)致系統(tǒng)需要更頻繁地進(jìn)行內(nèi)存管理操作,如內(nèi)存交換或殺死后臺(tái)進(jìn)程,以釋放足夠的內(nèi)存給前臺(tái)應(yīng)用。不僅可能影響前臺(tái)應(yīng)用的性能,還可能影響用戶的多任務(wù)體驗(yàn)。
依賴largeHeap來解決內(nèi)存問題并不是一種長期或可持續(xù)的解決方案。更好的做法應(yīng)該是優(yōu)化應(yīng)用的內(nèi)存使用,確保應(yīng)用能夠高效地管理其內(nèi)存資源。
largeHeap屬性并不能保證應(yīng)用一定能夠獲得更多的內(nèi)存。即使設(shè)置了largeHeap="true",系統(tǒng)仍然會(huì)根據(jù)設(shè)備的總內(nèi)存、其他應(yīng)用的內(nèi)存需求以及系統(tǒng)的內(nèi)存管理策略來決定實(shí)際分配給應(yīng)用的內(nèi)存大小。