您現在的位置是:電腦技術吧?>? 組裝維修 ??>??話永遠不會掉在地上,什么東西往上升永遠不會往下掉??>??正文詳情

話永遠不會掉在地上,什么東西往上升永遠不會往下掉

堂夏容2019-12-16 13:02:03 人圍觀
簡介是最里面兩個板牙永遠不會掉Android系統有自己的內存管理方法。為了保證系統的有序穩定運行,系統會自動分配和控制程序的內存使用。當系統認為當前的資源非常有限時,為了保證一

Android 系統對于內存管理有自己的一套方法,為了保障系統有序穩定的運信,系統內部會自動分配,控制程序的內存使用。

當系統覺得當前的資源非常有限的時候,為了保證一些優先級高的程序能運行,就會殺掉一些他認為不重要的程序或者服務來釋放內存。

這樣就能保證真正對用戶有用的程序仍然再運行。

如果你的 Service 碰上了這種情況,多半會先被殺掉。

但如果你增加 Service 的優先級就能讓他多留一會,我們可以用 setForeground(true) 來設置 Service 的優先級。

為什么是 foreground ? 默認啟動的 Service 是被標記為 background,當前運行的 Activity 一般被標記為 foreground,也就是說你給 Service 設置了 foreground 那么他就和正在運行的 Activity 類似優先級得到了一定的提高。

當讓這并不能保證你得 Service 永遠不被殺掉,只是提高了他的優先級。

有一個方法可以給你更清晰的演示,進入 $SDK/tools 運行命令復制代碼# adb shell dumpsys activity|grep oom_adj Running Norm Proc # 6: oom_adj= 0 ProcessRecord{43635cf0 12689:com.roiding.netraffic/10028} Running Norm Proc # 5: oom_adj= 7 ProcessRecord{436feda0 12729:com.android.browser/10006} Running Norm Proc # 4: oom_adj= 8 ProcessRecord{4367e838 12761:android.process.acore/10016} Running Norm Proc # 3: oom_adj= 8 ProcessRecord{43691cd8 12754:com.google.process.gapps/10000} Running PERS Proc # 1: oom_adj=-12 ProcessRecord{43506750 5941:com.android.phone/1001} Running PERS Proc # 0: oom_adj=-100 ProcessRecord{4348fde0 5908:system/1000}復制代碼返回的一大堆東西,觀察 oom_adj 的值,如果是大于 8 一般就是屬于 backgroud 隨時可能被干掉,數值越小證明優先級越高,被干掉的時間越晚。

你看phone的程序是 -12 說明電話就是電話,其他什么都干了了,也的能接電話對吧。

另外還有一個 -100 的,更邪乎因為是 system 如果他也完蛋了,你得系統也就掛了。

我是天王蓋地虎的分割線 從Android 1.5開始,一個已啟動的service可以調用startForeground(int, Notification)將service置為foreground狀態,調用stopForeground(boolean)將service置為 background狀態。

我們會在調用startForeground(int, Notification)傳入參數notification,它會在狀態欄里顯示正在進行的foreground service。

background service不會在狀態欄里顯示。

在Android 1.0中,將一個service置為foreground狀態:setForeground(true);mNM.notify(id, notification);將一個service置為background狀態:mNM.cancel(id);setForeground(false);對比看出,在1.0 API中調用setForeground(boolean)只是簡單的改變service的狀態,用戶不會有任何覺察。

新API中強制將 notification和改變service狀態的動作綁定起來,foreground service會在狀態欄顯示,而background service不會。

我是天王蓋地虎的分割線 通過在androidmanifest.xml中的application標簽中加入android:persistent=true屬性后的確就能夠達到保證該應用程序所在進程不會被LMK殺死。

但有個前提就是應用程序必須是系統應用,也就是說應用程序不能采用通常的安裝方式。

必須將應用程序的apk包直接放到/system/app目錄下。

而且必須重啟系統后才能生效。

除了一般的幾種優先級外,還存在著coreserver,system這樣的永遠不會被LMK回收的優先級。

系統中的電話應用就是coreserver優先級的。

通過查看源代碼可以知道,只有應用程序的flag同時為FLAG_SYSTEM和FLAG_PERSISTENT時,才會被設置為coreserver優先級if ((info.flags(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) { app.persistent = true; app.maxAdj = CORE_SERVER_ADJ; }FLAG_SYSTEM在應用程序apk放在/system/app下時會被設置。

所以才會出現只設置android:persistent=true仍然會被殺死的情況。

測試時發現,將應用程序放到/system/app后不重啟系統,仍然會被識別為普通的進程。

當系統重新啟動時,會在一開始就啟動該進程并把它優先級設置為coreserver。

通過dumpsys activity命令能夠很明顯的看出其中差別。

復制代碼Running processes (most recent first): App # 3: adj= 2/1 ProcessRecord{30858c20 1877:com.android.email/10014} (started-services) PERS # 2: adj=-100/0 ProcessRecord{308fb390 1713:system/1000} (fixed) App # 1: adj= 0/0 ProcessRecord{30908198 1794:android.process.acore/10005} (top-activity) PERS # 0: adj= -12/0 ProcessRecord{3090d488 1789:xiao.xiong.test/10026} (fixed)復制代碼而且adj=-12時,這個進程通過ddms手動stop后會立即啟動我是天王蓋地虎的分割線 方法對于一個service,可以首先把它設為在前臺運行:復制代碼public void MyService.onCreate() { super.onCreate(); Notification notification = new Notification(android.R.drawable.my_service_icon,my_service_name,System.currentTimeMillis()); PendingIntent p_intent = PendingIntent.getActivity(this, 0, new Intent(this, MyMainActivity.class), 0); notification.setLatestEventInfo(this, MyServiceNotification, MyServiceNotification is Running!,p_intent); Log.d(TAG, String.format(notification = %s, notification)); startForeground(0x1982, notification); // notification ID: 0x1982, you can name it as you will.}復制代碼相較于/data/app下的應用,放在/system/app下的應用享受更多的特權,比如若在其Manifest.xml文件中設置persistent屬性為true,則可使其免受out-of-memory killer的影響。

如應用程序'Phone'的AndroidManifest.xml文件:application android:name=PhoneApp android:persistent=true android:[email protected]/dialerIconLabel android:[email protected]/ic_launcher_phone ... /application設置后app提升為系統核心級別,任何情況下不會被kill掉, settings-applications里面也會屏蔽掉stop操作。

復制代碼這樣設置前的log: Proc #19: adj=svc/B 4067b028 255:com.xxx.xxx/10001 (started-services) # cat /proc/255/oom_adj 4設置后的log: PERS #19: adj=core /F 406291f0 155:com.xxx.xxx/10001 (fixed) # cat /proc/155/oom_adj -12 # 這是CORE_SERVER_ADJ注:init進程的oom_adj為-16(即SYSTEM_ADJ): cat /proc/1/oom_adj復制代碼Android相關部分分析在文件frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中有以下的代碼:復制代碼final ProcessRecord addAppLocked(ApplicationInfo info) { ProcessRecord app = getProcessRecordLocked(info.processName, info.uid); if (app == null) { app = newProcessRecordLocked(null, info, null); mProcessNames.put(info.processName, info.uid, app); updateLruProcessLocked(app, true, true); } if ((info.flags(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) { app.persistent = true; app.maxAdj = CORE_SERVER_ADJ; // 這個常數值為-12。

} if (app.thread == null mPersistentStartingProcesses.indexOf(app) 0) { mPersistentStartingProcesses.add(app); startProcessLocked(app, added application, app.processName); } return app; }復制代碼可見要想成為core service (即app.maxAdj = CORE_SERVER_ADJ(-12)),應用程序需要FLAG_SYSTEM和FLAG_PERSISTENT兩個標志,FLAG_SYSTEM指的是應用位于/system/app下,FLAG_PERSISTENT就是指persistent屬性。

而對于frameworks/base/services/java/com/android/server/SystemServer.java,則調用ActivityManagerService.setSystemProcess();把自己的 app.maxAdj 設置成SYSTEM_ADJ,即-16。

我是天王蓋地虎的分割線 Android中的進程是托管的,當系統進程空間緊張的時候,會依照優先級自動進行進程的回收。

由此帶來三個問題:回收規則: 什么時候回收與回收哪一個?

避免誤殺: 如何阻止被回收?

數據恢復與保存: 被回收了怎么辦?

Android將進程分為6個等級,它們按優先級順序由高到低依次是:前臺進程( FOREGROUND_APP)可視進程(VISIBLE_APP )次要服務進程(SECONDARY_SERVER )后臺進程 (HIDDEN_APP)內容供應節點(CONTENT_PROVIDER)空進程(EMPTY_APP)特征:如果一個進程里面同時包含service和可視的activity,那么這個進程應該歸于可視進程,而不是service進程。

另外,如果其他進程依賴于它的話,一個進程的等級可以提高。

例如,一個A進程里的service被綁定到B進程里的組件上,進程A將總被認為至少和B進程一樣重要。

系統中的phone服務被劃分到前臺進程而不是次要服務進程.在android中,進程的oom_adj值也就代表了它的優先級。

oom_adj值越高代表該進程優先級越低。

文件/init.rc中有以下屬性設置:setprop ro.FOREGROUND_APP_ADJ 0 setprop ro.VISIBLE_APP_ADJ 1 setprop ro.SECONDARY_SERVER_ADJ 2 setprop ro.HIDDEN_APP_MIN_ADJ 7 setprop ro.CONTENT_PROVIDER_ADJ 14 setprop ro.EMPTY_APP_ADJ 15/init.rc中,將PID為1的進程(init進程)的oom_adj設置為SYSTEM_ADJ(-16):# Set init its forked children's oom_adj. write /proc/1/oom_adj 16查看本機設置:cat /sys/module/lowmemorykiller/parameters/adj0,1,2,7,14,15回收時,文件/init.rc中:setprop ro.FOREGROUND_APP_MEM 1536 // 6M setprop ro.VISIBLE_APP_MEM 2048 // 8M setprop ro.SECONDARY_SERVER_MEM 4096 // 16M setprop ro.HIDDEN_APP_MEM 5120 // 20M setprop ro.CONTENT_PROVIDER_MEM 5632 // 22.4M setprop ro.EMPTY_APP_MEM 6144 // 24M這些數字也就是對應的內存閾值,一旦低于該值,Android便開始按順序關閉相應等級的進程。

注意這些數字的單位是page: 1 page = 4 kB。

所以上面的六個數字對應的就是(MB): 6,8,16,20,22,24。

查看現在的內存閾值設置:cat /sys/module/lowmemorykiller/parameters/minfree要想重新設置該值(對應不同的需求):echo 1536,2048,4096,5120,15360,23040/sys/module/lowmemorykiller/parameters/minfree這樣當可用內存低于90MB的時候便開始殺死空進程,而當可用內存低于60MB的時候才開始殺死內容供應節點類進程。

具體的回收實現在ActivityManagerService.java中的函數trimApplications():首先移除package已被卸載的無用進程;基于進程當前狀態,更新oom_adj值,然后進行以下操作:1) 移除沒有activity在運行的進程;2) 如果AP已經保存了所有的activity狀態,結束這個AP。

最后,如果目前還是有很多activities 在運行,那么移除那些activity狀態已經保存好的activity。

更新oom_adj的值:在ActivityManagerService.java文件的ComputeOomAdjLocked() 中計算出進程的oom_adj,例如:if (app == TOP_APP) { // The last app on the list is the foreground app. adj = FOREGROUND_APP_ADJ; app.adjType = top-activity; }我是天王蓋地虎的分割線 Android kernel中的low memory killerAndroid的Low Memory Killer根據需要(當系統內存短缺時)殺死進程釋放其內存,源代碼在kernel/drivers/misc/lowmemorykiller.c中。

簡單說,就是尋找一個最合適的進程殺死,從而釋放它占用的內存。

最合適的進程是:oom_adj越大占用物理內存越多一旦一個進程被選中,內核會發送SIGKILL信號將之殺死:復制代碼for_each_process(p) { if(selected == NULL || p-oomkilladj selected-oomkilladj || (p-oomkilladj == selected-oomkilladj tasksize selected_tasksize)) { selected = p; } } if(selected != NULL) { force_sig(SIGKILL, selected); }復制代碼查看LRU列表:adb shell dumpsys activity當activitydemo在前臺時:包含Service的進程的優先級比較高,在computeOomAdjLocked中將其分為了兩小類:復制代碼static final int MAX_SERVICE_INACTIVITY = 30*60*1000; if (now (s.lastActivity MAX_SERVICE_INACTIVITY)) { if (adj SECONDARY_SERVER_ADJ) { adj = SECONDARY_SERVER_ADJ; app.adjType = started-services; app.hidden = false; } } if (adj SECONDARY_SERVER_ADJ) { app.adjType = started-bg-services; }復制代碼完全讓進程不被kill是不可能的,我們可以通過一些操作,使進程被kill的幾率變小:提高進程的優先級:* 后臺操作采用運行于前臺的Service形式,因為一個運行著service的進程比一個運行著后臺activity的等級高;* 按back鍵使得進程中的activity在后臺運行而不是destory,需重載back按鍵(沒有任何activity在運行的進程優先被殺).* 依賴于其他優先級高的進程;強制修改進程屬性:* 在進程中設置:setPersistent(true);* 在Manifest文件中設置(如上)。

版權聲明:本文由 堂夏容 整理編輯。

原標題:視頻照片存在哪里永遠不會掉,不仰望星空的人永遠不會掉坑里

轉載注明出處:http://www.dn9ww09s.icu/assemble/15479.html

文章評論

    共有條評論來說兩句吧...

    用戶名:

    驗證碼:

作者推薦

  • 分頁的實現思路,通用的分頁思路

    分頁的實現思路,通用的分頁思路 相關圖片分頁查詢思路在搜索復雜條件時,somefield somefieldmysql排序的東西會搜索數據庫,找到所有符合條件的記錄,然后取出M,n條記錄。如果你有數十萬條數據,用js分頁...

  • 輕松轉聯盟,輕松轉奶

    輕松轉聯盟,輕松轉奶 相關圖片廣信貸簡單賺如何轉輕松賺將SQL數據庫傳輸到access數據庫的步驟如下:1。建立access數據庫:在access中建立access數據庫和表,access字段類型與SQL字段類型的轉奶技巧...

  • oracle存儲過程是什么,oracle存儲過程詳解

    oracle存儲過程是什么,oracle存儲過程詳解 相關圖片oracle如何調用存儲過程如果不小心覆蓋了上一個存儲過程,則需要刷新。時間越長,閃回的可能性就越小。這是恢復原則。如果不小心覆蓋了上一個存儲過程,則需要刷新。時間越長,...

  • 應用程序大小,應用程序窗口大小調整

    應用程序大小,應用程序窗口大小調整 相關圖片縮小應用程序窗口問:如何使我的安裝包更小,下載和安裝程序更快?答:本文收集了一些關于減小安裝包大小的技巧(在第一次下載和安裝程序時)。如果是升級程序,您可以閱讀本...

  • SciPy入門指南,grails 入門指南

    SciPy入門指南,grails 入門指南 相關圖片php入門指南本文主要介紹JavaScript的requirejs庫的介紹指南。近年來,requirejs庫的普及程度迅速提高。您可以參考目前最常用的JavaScript庫之明日之后新手入門指南...

  • 怎樣添加控件,vs如何添加控件

    怎樣添加控件,vs如何添加控件 相關圖片如何添加文本框控件看到后臺有很多網頁,刪除內容時會有一個確認對話框,可以很好的避免意外刪除,所以我也想在我的asp.net項目中添加這個功能,研究一下,最后采取刪除確認的功...

  • php文本寫入,php打開文件寫入內容

    php文本寫入,php打開文件寫入內容 相關圖片進入php怎么建文件本文的例子描述了如何在PHP中讀寫tab分隔的文件。與您分享以供參考。具體分析如下:該PHP代碼實現了對tab分離文件的讀寫,包括兩個獨立的函數,一個是讀寫,如p...

  • iframe,if name==main

    iframe,if name==main 相關圖片if函數顯示name本文主要介紹if\\\\\\\\\\\\\\\\\\\\\\\\\\\__#name什么意思...

  • java項目打包成jar包,web項目打包成jar包

    java項目打包成jar包,web項目打包成jar包 相關圖片eclipse打包成jar在做Android項目時,我們經常會遇到以下需求:將一些已經完成的項目集成到當前項目中,并以某種方式將以前項目的類和資源移動到當前項目中。接下來,我將介紹以前項...

  • 彩票開獎查詢排列5列5,彩票開獎查詢排列3

    彩票開獎查詢排列5列5,彩票開獎查詢排列3 相關圖片排列五歷史開獎結果前段時間客戶提出了一個需求,就是想讓查詢的結果隨機排序一下。查詢了很多東西說的很是不明白,最后解決了問題。方案如下:  只是在ORDER BY 后面加上一些...

熱評文章

  • excel生成文件夾目錄,生成pdf

    excel生成文件夾目錄,生成pdf 相關圖片如何制作pdf格式文件如果我們與其他人共享模塊,我們希望Access2000將刪除可編輯的源代碼。這樣,VBA程序可以繼續運行,但其他用戶無法查看或編輯它。我們可以通過單擊“工具”,...

  • 小米主題設置自定義,同花順自定義界面設置

    小米主題設置自定義,同花順自定義界面設置 相關圖片吃雞自定義布局設置微軟推出的Windows 8和Windows 10操作系統中,有近兩個采用了向導界面風格。事實上,在現代UI(新用戶界面)中也有類似的界面樣式。如果用戶設計了歡微信發現界面...

  • exists和in的區別,數據庫exists與in的區別

    exists和in的區別,數據庫exists與in的區別 相關圖片not exists用法本文的例子說明了在PHP中存在ISSET和ARRAYXKEY的區別。與您分享以供參考。具體分析如下:1。數組值的判斷不同。對于NULL或“OR”或“false”mysql exists用法...

  • u盤寫入無響應,軟碟通寫入無響應

    u盤寫入無響應,軟碟通寫入無響應 相關圖片寫入ISO失敗將asp生成的內容寫入響應流的最有效方法是什么?使用ASP的主要原因之一是在服務器上生成動態內容。因此,顯然,我們測試的起點是確定將動態內容發送到響應流的最合適...

  • 上傳參數亂碼,request參數亂碼

    上傳參數亂碼,request參數亂碼 相關圖片ajax傳遞中文參數亂碼計算機誕生于美國,英語是他的母語,其他語言是他的外語。像我們一樣,不管他掌握得多好,他也不會像母語那樣使用外語。他經常犯一些拼寫錯誤。產生誤碼的...

  • winform嵌入html,ashx引用到html5中

    winform嵌入html,ashx引用到html5中 相關圖片mysql下載本文主要介紹了HTML ashx表單提交的具體實現。對于您的朋友,請參考以下1。sumbit form submission webform1.aspx的源代碼ashx如何寫控件的點擊事件...

  • iOS3D游戲,ios 3dtouch

    iOS3D游戲,ios 3dtouch 相關圖片ios3dtouch在哪開首先需要獲取mono.data.sqlite.dll文件和system.data.dll文件。如果你在MAC上使用unity,那就太悲劇了。我找不到這兩個文件,3dtouch怎么用...

  • 如何調整列寬,如何調整表格的行高和列寬

    如何調整列寬,如何調整表格的行高和列寬 相關圖片excel自動調整行高列寬DataGridView有一個名為autosizecolumnmode的屬性,它有幾個枚舉值:1。所有單元格調整列寬以適應列中所有單元格(包括標題單元格)的內容如何設置列寬...

  • memcached安裝,memcached安裝教程

    memcached安裝,memcached安裝教程 相關圖片memcached教程本文主要介紹在PHP中安裝memcached擴展的注意事項。本文介紹了服務器的安裝、launchpad、memcached擴展的安裝以及php.ini的配置。對緩存memcached...

  • 字符串去掉空格,c去掉字符串的空格

    字符串去掉空格,c去掉字符串的空格 相關圖片去掉字符串中的某個字符一。弦。Trim()Trim()是刪除第一個和最后一個空格。2。replace(,);要刪除所有空格,包括第一個和最后一個空格,中間代碼如下:String St字符串刪除空格...

關注微信

变脸官网查询