簡體   English   中英

修復 OutOfMemoryErrors

[英]Fixing OutOfMemoryErrors

大家好,我發現在我們最近的 Android 版本中,有關 memory 泄漏的崩潰大幅增加。 我們已經做了一些事情來嘗試緩解這些問題,但在最新版本中仍然看到同樣的崩潰。

 Fatal Exception: java.lang.OutOfMemoryError
 Failed to allocate a 16 byte allocation with 1890136 free bytes and 1845KB until OOM, target footprint 201326592, growth limit 201326592; failed due to fragmentation (largest possible contiguous allocation 54788096 bytes)
 java.lang.Long.valueOf (Long.java:845)
 io.reactivex.internal.operators.observable.ObservableInterval$IntervalObserver.run (ObservableInterval.java:82)
 io.reactivex.Scheduler$PeriodicDirectTask.run (Scheduler.java:562)
 io.reactivex.Scheduler$Worker$PeriodicTask.run (Scheduler.java:509)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run (ExecutorScheduler.java:288)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run (ExecutorScheduler.java:253)
 java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
 java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
 java.lang.Thread.run (Thread.java:923)
 Fatal Exception: java.lang.OutOfMemoryError
 Failed to allocate a 16 byte allocation with 1590248 free bytes and 1552KB until OOM, target footprint 201326592, growth limit 201326592; failed due to fragmentation (largest possible contiguous allocation 39845888 bytes)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.schedule (ExecutorScheduler.java:161)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.schedule (ExecutorScheduler.java:187)
 io.reactivex.Scheduler$Worker$PeriodicTask.run (Scheduler.java:531)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run (ExecutorScheduler.java:288)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run (ExecutorScheduler.java:253)
 java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
 java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
 java.lang.Thread.run (Thread.java:923)
 Fatal Exception: java.lang.OutOfMemoryError
 Failed to allocate a 16 byte allocation with 1215008 free bytes and 1186KB until OOM, target footprint 201326592, growth limit 201326592; failed due to fragmentation (largest possible contiguous allocation 49020928 bytes)
 io.reactivex.internal.queue.MpscLinkedQueue.offer (MpscLinkedQueue.java:62)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.schedule (ExecutorScheduler.java:167)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.schedule (ExecutorScheduler.java:187)
 io.reactivex.Scheduler$Worker$PeriodicTask.run (Scheduler.java:531)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run (ExecutorScheduler.java:288)
 io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run (ExecutorScheduler.java:253)
 java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
 java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
 java.lang.Thread.run (Thread.java:923)

是否存在觸發這些問題的某些框架更改,是否是導致此問題的應用程序代碼? 嘗試解決上述崩潰的一些策略是什么?

除了現有評論之外,還需要考慮其他一些技術:

現場儀表:

活動模式:如果您有記錄用戶活動的內容,請查找 go 長時間沒有崩潰的應用程序和較早崩潰的應用程序,看看用戶是否執行了不同的操作

直接 Memory 用法:由於您還無法在調試版本中重現此問題,您可以記錄在特定活動之前和之后可用的 memory,以幫助您縮小在應用程序中發生這種情況的位置。 您可以訪問可用的應用程序 memory ,然后記錄它(如果您可以獲得日志)或通過某些分析系統將其報告回來。

本地測試:

(使用 Leak Canary 或分析器)

通常有一些時間點應該回到與分配的 memory 相同的水平:例如,如果您 go 進入屏幕並返回,您可能會分配一些 static 項目,但是從第二次使用屏幕開始,您將需要 memory回到正常(靜止)點。 所以停止執行,強制 GC,重新啟動執行並完成工作流,然后返回主屏幕。 (再次跳過第一次)可以是縮小哪個工作流留下大量額外 memory 的好方法。

調試版本沒有產生這種效果是不尋常的,如果你有一個“友好的”最終用戶報告這個問題,也許給他們一個調試版本並請求他們通過使用它來支持你。

在調試環境中,您還可以嘗試“讓它變得更糟”,例如,go 進出屏幕或工作流 10 次或 100 次(針對 100 次示例編寫腳本)。

您不能動態增加堆大小,但可以通過使用請求使用更多。

android:largeHeap="true"

manifest.xml中,您可以在清單中添加這些行,它適用於某些情況。

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

您的應用程序進程是否應使用大型 Dalvik 堆創建。 這適用於為應用程序創建的所有進程。 它僅適用於加載到進程中的第一個應用程序; 如果您使用共享用戶 ID 來允許多個應用程序使用一個進程,則它們都必須一致地使用此選項,否則它們將產生不可預知的結果。 大多數應用不需要這個,而是應該專注於減少整體 memory 使用以提高性能。 啟用此功能也不能保證可用 memory 的固定增加,因為某些設備受其總可用 memory 的限制。

要在運行時查詢可用的 memory 大小,請使用方法 getMemoryClass() 或 getLargeMemoryClass()。

使用Coroutines進行長時間或繁重的操作。 這些崩潰來自Rxjava 也許您在這方面沒有准確地執行工作。

我只是想看看您可以查看的位置,從堆棧跟蹤來看,您似乎正在使用計划執行任務。 我懷疑您正在運行多個線程,並且由於每個線程都需要自己分配 memory ,因此需要考慮的一些事情是:通過線程池控制線程數,這將限制可用線程數並回收線程而不是分配新線程並可能同時運行大量線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM