Я реализовал BackupAgent, следуя рекомендациям для Резервное копирование данных. Код ведет себя так, как ожидалось, пока StrictMode.VmPolicy
не будет настроен на обнаружение утечки закрываемых объектов. После выполнения резервного копирования и сборки мусора CloseGuard сообщает об утечке ParcelFileDescriptor
со следующей трассировкой стека:
06-28 21:47:39.683 25072-25081/com.qbix.nub E/StrictMode﹕ A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
java.lang.Throwable: Explicit termination method 'close' not called
at dalvik.system.CloseGuard.open(CloseGuard.java:184)
at android.os.ParcelFileDescriptor.<init>(ParcelFileDescriptor.java:179)
at android.os.ParcelFileDescriptor$1.createFromParcel(ParcelFileDescriptor.java:905)
at android.os.ParcelFileDescriptor$1.createFromParcel(ParcelFileDescriptor.java:897)
at android.app.IBackupAgent$Stub.onTransact(IBackupAgent.java:64)
at android.os.Binder.execTransact(Binder.java:404)
at dalvik.system.NativeStart.run(Native Method)
06-28 21:47:39.683 25072-25081/com.qbix.nub W/System.err﹕ StrictMode VmPolicy violation with POLICY_DEATH; shutting down.
06-28 21:47:39.683 25072-25081/com.qbix.nub I/Process﹕ Sending signal. PID: 25072 SIG: 9
Чтобы убедиться, что у меня не было утечки ParcelFileDescriptor
в моем BackupAgent
, я вставил onBackup()
вот так:
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException {
if (oldState != null) {
oldState.close();
}
newState.close();
return;
}
Это изменение не устранило утечку.
Вот шаги, которые я использую для воспроизведения проблемы:
- Измените данные приложения, чтобы вызвать вызов
BackupManager.dataChanged()
- Используйте
adb shell bmgr run
для принудительного выполнения операции резервного копирования - Запустить сборщик мусора с
Android Studio
Я недостаточно знаю о связанных службах, чтобы понять, дает ли трассировка стека подсказки о том, происходит ли утечка в системе BackupService
или вызвана ошибкой в моем коде, которую я не вижу. Продолжающееся возникновение утечки при работе с заглушкой onBackup()
подсказывает мне, что утечка связана с сервисом.
Изучая эту проблему, я обнаружил, что за последние несколько месяцев были опубликованы другие проблемы, которые включали тот же отчет об утечке в их logcats
:
Проблемы с навигационным ящиком в Android
Android - HTTP Get - явное завершение не называется ошибкой. Что мне не хватает?
Устранение исключения java.lang.Throwable в Android
Показанный выше logcat взят с устройства KitKat. Я думаю, что на другом устройстве, на котором запущен Lollipop, возникает та же ошибка. Приложение убито, но logcat не включает дамп CloseGuard. Не знаю, что мне нужно сделать, чтобы это увидеть.
onBackup()
подсказывает мне, что утечка происходит в сервисе - я согласен. OTOH, я не видел сообщений об этом, и я ожидал бы их, если бы каждая резервная копия в основном содержалаParcelFileDescriptor
. Я ненавижу систему резервного копирования по соображениям конфиденциальности и безопасности, поэтому я не использовал ее лично. - person CommonsWare   schedule 30.06.2015