android dalvik heap 引數解析
android 系統中可以在prop中配置dalvik堆的有關設定。具體設定由如下三個屬性來控制
-dalvik.vm.heapstartsize
堆分配的初始大小,調整這個值會影響到應用的流暢性和整體ram消耗。這個值越小,系統ram消耗越慢,
但是由於初始值較小,一些較大的應用需要擴張這個堆,從而引發gc和堆調整的策略,會應用反應更慢。
相反,這個值越大系統ram消耗越快,但是程式更流暢。
-dalvik.vm.heapgrowthlimit
受控情況下的極限堆(僅僅針對dalvik堆,不包括native堆)大小,dvm heap是可增長的,但是正常情況下
dvm heap的大小是不會超過dalvik.vm.heapgrowthlimit的值(非正常情況下面會詳細說明)。這個值控制那
些受控應用的極限堆大小,如果受控的應用dvm heap size超過該值,則將引發oom(out of memory)。
-dalvik.vm.heapsize
不受控情況下的極限堆大小,這個就是堆的最大值。不管它是不是受控的。這個值會影響非受控應用的dalvik
heap size。一旦dalvik heap size超過這個值,直接引發oom。
用他們三者之間的關係做一個簡單的比喻:分配dalvik heap就好像去食堂打飯,有人飯量大,要吃三碗,有人飯量小,連一碗都吃不完。如果食堂按照三碗的標準來給每個人打飯,那絕對是鋪張浪費,所以食堂的策略就是先打一碗,湊合吃,不夠了自己再來加,設定堆大小也是一樣,先給一個合理值,湊合用,自己不夠了再跟系統要。食堂畢竟是做買賣的,如果很多人明顯吃不了那麼多,硬是一碗接著一碗。為了制止這種不合理的現象,食堂又定了一個策略,一般人就只能吃三碗。但是如果虎背熊腰的大漢確實有需要,可以吃上五碗,超過五碗就不給了(太虧本了)。
開始給一碗 對應 dalvik.vm.heapstartsize
一般人最多吃三碗 對應 dalvik.vm.heapgrowthlimit
虎背熊腰的大漢最多能吃五碗 對應 dalvik.vm.heapsize
在android開發中,如果要使用大堆。需要在manifest中指定android:largeHeap為true。這樣dvm heap最大可達dalvik.vm.heapsize。其中分配過程,可以在heap.cpp裡粗略看出一些原理:
- /* Try as hard as possible to allocate some memory.
- */
- staticvoid *tryMalloc(size_t size)
- {
- void *ptr;
- /* Don't try too hard if there's no way the allocation is
- * going to succeed. We have to collect SoftReferences before
- * throwing an OOME, though.
- */
- if (size >= gDvm.heapGrowthLimit) {
- LOGW("%zd byte allocation exceeds the %zd byte maximum heap size",
- size, gDvm.heapGrowthLimit);
- ptr = NULL;
- goto collect_soft_refs;
- }
- //TODO: figure out better heuristics
- // There will be a lot of churn if someone allocates a bunch of
- // big objects in a row, and we hit the frag case each time.
- // A full GC for each.
- // Maybe we grow the heap in bigger leaps
- // Maybe we skip the GC if the size is large and we did one recently
- // (number of allocations ago) (watch for thread effects)
- // DeflateTest allocs a bunch of ~128k buffers w/in 0-5 allocs of each other
- // (or, at least, there are only 0-5 objects swept each time)
- ptr = dvmHeapSourceAlloc(size);
- if (ptr != NULL) {
- return ptr;
- }
- /*
- * The allocation failed. If the GC is running, block until it
- * completes and retry.
- */
- if (gDvm.gcHeap->gcRunning) {
- /*
- * The GC is concurrently tracing the heap. Release the heap
- * lock, wait for the GC to complete, and retrying allocating.
- */
- dvmWaitForConcurrentGcToComplete();
- ptr = dvmHeapSourceAlloc(size);
- if (ptr != NULL) {
- return ptr;
- }
- }
- /*
- * Another failure. Our thread was starved or there may be too
- * many live objects. Try a foreground GC. This will have no
- * effect if the concurrent GC is already running.
- */
- gcForMalloc(false);
- ptr = dvmHeapSourceAlloc(size);
- if (ptr != NULL) {
- return ptr;
- }
- /* Even that didn't work; this is an exceptional state.
- * Try harder, growing the heap if necessary.
- */
- ptr = dvmHeapSourceAllocAndGrow(size);
- if (ptr != NULL) {
- size_t newHeapSize;
- newHeapSize = dvmHeapSourceGetIdealFootprint();
- //TODO: may want to grow a little bit more so that the amount of free
- // space is equal to the old free space + the utilization slop for
- // the new allocation.
- LOGI_HEAP("Grow heap (frag case) to "
- "%zu.%03zuMB for %zu-byte allocation",
- FRACTIONAL_MB(newHeapSize), size);
- return ptr;
- }
- /* Most allocations should have succeeded by now, so the heap
- * is really full, really fragmented, or the requested size is
- * really big. Do another GC, collecting SoftReferences this
- * time. The VM spec requires that all SoftReferences have
- * been collected and cleared before throwing an OOME.
- */
- //TODO: wait for the finalizers from the previous GC to finish
- collect_soft_refs:
- LOGI_HEAP("Forcing collection of SoftReferences for %zu-byte allocation",
- size);
- gcForMalloc(true);
- ptr = dvmHeapSourceAllocAndGrow(size);
- if (ptr != NULL) {
- return ptr;
- }
- //TODO: maybe wait for finalizers and try one last time
- LOGE_HEAP("Out of memory on a %zd-byte allocation.", size);
- //TODO: tell the HeapSource to dump its state
- dvmDumpThread(dvmThreadSelf(), false);
- return NULL;
- }
這裡分為如下幾個動作
1 首先判斷一下需要申請的size是不是過大,如果申請的size超過了堆的最大限制,則轉入步驟6
2 嘗試分配,如果成功則返回,失敗則轉入步驟3
3 判斷是否gc正在進行垃圾回收,如果正在進行則等待回收完成之後,嘗試分配。如果成功則返回,失敗則轉入步驟4
4 自己啟動gc進行垃圾回收,這裡gcForMalloc的引數是false。所以不會回收軟引用,回收完成後嘗試分配,如果成功則返回,失敗則轉入步驟5
5 呼叫dvmHeapSourceAllocAndGrow嘗試分配,這個函式會擴張堆。所以heap startup的時候可以給一個比較小的初始堆,實在不夠用再呼叫它進行擴張
6 進入回收軟引用階段,這裡gcForMalloc的引數是ture,所以需要回收軟引用。然後呼叫dvmHeapSourceAllocAndGrow嘗試分配,如果失敗則丟擲OOM
如果設定了largeHeap,具體流程從解析apk開始,原始碼位於PackagePaser.java中,其中parseApplication函式負責解析apk。其中有一個小段程式碼如下:
[java] view plaincopyprint?- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
- false)) {
- ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
- }
如果解析到apk中設定了largeHeap,則在applicationinfo中新增FLAG_LARGE_HEAP標籤。之後會在ActivityThead.java中的handleBindApplication處理,這個函式非常重要,底層process fork好之後,會由這個函式把上層應用繫結過去。並且呼叫上層應用的入口點。其中處理largeHeap的程式碼如下: [java] view plaincopyprint?
- if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
- dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
- }
這裡經過jni呼叫,最終回來到heapsource.cpp中的dvmClearGrowthLimit函式中: [cpp] view plaincopyprint?
- /*
- * Removes any growth limits. Allows the user to allocate up to the
- * maximum heap size.
- */
- void dvmClearGrowthLimit()
- {
- HS_BOILERPLATE();
- dvmLockHeap();
- dvmWaitForConcurrentGcToComplete();
- gHs->growthLimit = gHs->maximumSize;
- size_t overhead = oldHeapOverhead(gHs, false);
- gHs->heaps[0].maximumSize = gHs->maximumSize - overhead;
- gHs->heaps[0].limit = gHs->heaps[0].base + gHs->heaps[0].maximumSize;
- dvmUnlockHeap();
- }
相關推薦
android dalvik heap 引數解析
android 系統中可以在prop中配置dalvik堆的有關設定。具體設定由如下三個屬性來控制 -dalvik.vm.heapstartsize 堆分配的初始大小,調整這個值會影響到應用的流暢性和整體ram消耗。這個值越小,系統r
android dalvik heap 淺析
android 系統中可以在prop中配置dalvik堆的有關設定。具體設定由如下三個屬性來控制 -dalvik.vm.heapstartsize 堆分配的初始大小,調整這個值會影響到應用的流暢性和整體ram消耗。這個值越小,系統ram
Android Dalvik VM GC options 命令控制引數
} else if (strncmp(argv[i], "-Xgc:", 5) == 0) { //In VM thread, there is a register map for marking each stack item's status whether it is an object o
Android中的DrawRect()引數解析
官方文件中的定義: drawRect(float left, float top, float right, float bottom, Paint paint) Draw the specif
Android OTA升級包製作指令碼詳解(一,引數解析)
寫在前面: “build/tools/releasetools/ota_from_target_files -u lk.bin -n target.zip update.zip”這是製作整包的命令,很顯然這裡支援lk升級。本系列博文主要對該命令的執行流程及原理進
Android屬性動畫完全解析(上),初識屬性動畫的基本用法
fcm 操作 fad 擴展性 改變 內部使用 如果 轉載 @override 轉載請註明出處:http://blog.csdn.net/guolin_blog/article/details/43536355 在手機上去實現一些動畫效果算是件比較炫酷的事情,因此Andr
Android Dalvik虛擬機和ART虛擬機對比
x文件 開始 過程 優秀 clas 編譯 apk 但是 好的 1.概述 Android4.4以上開始使用ART虛擬機,在此之前我們一直使用的Dalvik虛擬機,那麽為什麽Google突然換了Android運行的虛擬機呢?答案只有一個:ART虛擬機更優秀。 2.Dalvik
Android ToolBar 使用完全解析
都是 主題 image 需要 oid primary 調用 blank ast ToolBar簡介 ToolBar是Android 5.0推出的一個新的導航控件用於取代之前的ActionBar,由於其高度的可定制性、靈活性、具有Material Design風格等優點,
Android源代碼解析之(六)-->Log日誌
static 同學 ons ets urn append oct source for 轉載請標明出處:一片楓葉的專欄 首先說點題外話,對於想學android framework源代碼的同學,事實上能夠在github中fork一份,詳細地址:p
Android源代碼解析之(四)-->HandlerThread
轉載 detail dcl red tag msg click 創建 tor 轉載請標明出處:一片楓葉的專欄 上一篇文章中我們解說了AsyncTast的基本使用以及實現原理,我們知道AsyncTask內部是通過線程池和Handler實現的。通過
以芯片直讀方式得到的Android全盤鏡像解析——DOS分區
xtend gpt 裏的 per 記錄 style 工作 計算 區號 最近得到了一個依舊用芯片直讀方式得到的Android全盤鏡像,這次是一個紅米手機的鏡像,和之前的鏡像不同,這次的分區類型的DOS分區,這裏說明一下,算是對之前那篇記錄的補充。 首先要糾正一下我的一
Android源代碼解析之(十三)-->apk安裝流程
solved 就是 activity 文章 空間不夠 orien gpo tpm systems 轉載請標明出處:一片楓葉的專欄 上一篇文章中給大家分析了一
Android源代碼解析之(七)-->LruCache緩存類
access ref trie ber tro double prot 推斷 rate 轉載請標明出處:一片楓葉的專欄 android開發過程中常常會用到緩
Android懸浮窗原理解析(Window)[源碼]
tco inflate 情況 tint input tdi scree list 接收 懸浮窗,在大多數應用中還是很少見的,目前我們接觸到的懸浮窗,差不多都是一些系統級的應用軟件,例如:360安全衛士,騰訊手機管家等;在某些服務行業如金融,餐飲等,也會在應用中添加懸浮窗,例
Android 中可變引數的使用 如:int...
每天積累一點點,時間久了,你就是大牛了 以前沒接觸過可變引數,見到就覺得挺新鮮的,特此記錄一下和大家分享。 1.可變引數的表示方式是物件後面加三個點(Object...),可以是 int...
URLParser:很實用的URL引數解析器(JAVA程式碼中方便獲取QueryString中的get引數)
很實用的URL引數解析器(JAVA程式碼中方便獲取QueryString中的get引數) package com.kaishustory.quick.commons.text; import java.io.UnsupportedEncodingException; import
【輸出文件】 Android 6 USB 模組解析
USB模組解析 簡介 主要完成USB 功能的切換和狀態的更新。通過接受kernel傳送過來的event訊息來確定USB狀態的切換並向外界傳送廣播訊息。
SpringMVC自動封裝List物件——自定義引數解析器
前臺傳遞的引數為集合物件時,後臺Controller希望用一個List集合接收資料。 原生SpringMVC是不支援,Controller引數定義為List型別時,接收引數會報如下錯誤: org.springframework.beans.BeanInstantiationException
Android版DesiredCapabilities引數配置
前言 每一個App測試都應指定是在什麼平臺下,那個裝置中執行那個App,而在Appium中主要是通過DesiredCapabilities來配置的。 DesiredCapabilities的作用,負責啟動服務時的引數配置;DesiredCapabilities的本質是key/value的物件。 &nbs
Android中Context引數解釋
context的作用,就是android應用連線service的橋樑。 比如Activity中有經常會有可能呼叫到系統的service,使用getSystemService()方法,這個方法調到最後,實際上是呼叫的ContextImpl的getSystemSer