當 Android 系統因記憶體不足或其他原因殺死應用進程時,正在執行的函數是否會被允許完成?
不會等待函數返回,直接殺死進程。 系統呼叫 Process.killProcess() 或類似機制終止進程時,所有執行緒會瞬間停止,後續代碼完全不會執行,包括 finally 區塊、onDestroy()、onStop() 等生命週期方法。
Android 根據進程類型分配 oom_adj 分數,分數越高越優先被殺:
| 進程類型 | 重要性 | oom_adj | 被殺機率 |
|---|---|---|---|
| 前台進程 | 用戶正在互動 | 0 | 極低 |
| 可見進程 | Activity 可見但非前台 | 100 | 低 |
| 服務進程 | 運行 started Service | 200 | 中 |
| 後台進程 | 無可見組件,含 stopped Activity | 400 | 高 |
| 空進程 | 無任何活躍組件 | 500+ | 最高 |
flush()/close() 可能導致資料損壞SharedPreferences apply():非同步寫入可能丟失// 壞例:依賴 onDestroy 寫入
@Override
protected void onDestroy() {
saveUserData(); // 進程被殺時不會執行!
}
// 好例:資料變更即寫入
private void updateUserName(String name) {
user.setName(name);
// 同步寫入關鍵資料
SharedPreferences.Editor editor = prefs.edit();
editor.putString("name", name);
editor.commit(); // 同步寫入,較 apply() 可靠
}
// 前台服務顯示持續通知,優先級接近前台進程
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("服務運行中")
.setSmallIcon(R.drawable.ic_service)
.build();
startForeground(SERVICE_ID, notification);
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level >= TRIM_MEMORY_RUNNING_LOW) {
// 清理圖片快取、釋放大型物件
imageCache.clear();
}
}
系統會在適當時機(充電、Wi-Fi、閒置)執行,即使進程被殺也會重新排程:
WorkRequest uploadWork = new OneTimeWorkRequest.Builder(UploadWorker.class).build();
WorkManager.getInstance(context).enqueue(uploadWork);
| 誤區 | 事實 |
|---|---|
onDestroy() 一定會被呼叫 | 進程被殺/崩潰/ANR 時不會呼叫 |
finally 區塊一定執行 | 進程級終止會繞過 JVM 正常關閉流程 |
| 靜態變數能跨進程存活 | 進程死即全失,除非持久化到磁碟 |
System.exit(0) 正常退出 | 會阻礙系統資源回收,極不推薦 |
Android 進程被殺是暴力、即時、不可攔截的。開發者不應依賴任何「臨終代碼」,而應採用即時持久化、前台服務、系統排程任務等機制保障資料安全與任務完成。