Я получал это предупреждение один раз в своем логарифме каждый раз, когда тестировал свое приложение.
W A resource failed to call close.
Я использовал следующий код, который нашел в Интернете, в своем методе onCreate()
, чтобы вызвать исключение и трассировку стека, чтобы выяснить, что его вызвало.
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder(StrictMode.getVmPolicy()).detectLeakedClosableObjects().build());
Это привело к следующей трассировке стека.
StrictMode policy violation: android.os.strictmode.LeakedClosableViolation: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
at android.os.StrictMode$AndroidCloseGuardReporter.report(StrictMode.java:1994)
at dalvik.system.CloseGuard.warnIfOpen(CloseGuard.java:336)
at java.io.FileInputStream.finalize(FileInputStream.java:508)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:339)
at java.lang.Daemons$FinalizerDaemon.processReference(Daemons.java:324)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:300)
at java.lang.Daemons$Daemon.run(Daemons.java:145)
at java.lang.Thread.run(Thread.java:1012)
Caused by: java.lang.Throwable: Explicit termination method 'close' not called
at dalvik.system.CloseGuard.openWithCallSite(CloseGuard.java:288)
at dalvik.system.CloseGuard.open(CloseGuard.java:257)
at java.io.FileInputStream.<init>(FileInputStream.java:176)
at edu.cmu.pocketsphinx.Assets.getExternalItems(Assets.java:149)
at edu.cmu.pocketsphinx.Assets.syncAssets(Assets.java:253)
at com.example.atest.MainActivity$SetupTask.doInBackground(MainActivity.java:127)
at com.example.atest.MainActivity$SetupTask.doInBackground(MainActivity.java:118)
at android.os.AsyncTask$3.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:264)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
который я проследил до этого кода..
private static class SetupTask extends AsyncTask<Void, Void, Exception> {
WeakReference<MainActivity> activityReference;
SetupTask(MainActivity activity) {
this.activityReference = new WeakReference<>(activity);
}
@Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(activityReference.get());
File assetDir = assets.syncAssets();
activityReference.get().setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
@Override
protected void onPostExecute(Exception result) {
if (result != null) {
((TextView) activityReference.get().findViewById(R.id.status_text)).setText(R.string.status_fail);
Log.d(TAG, "SetupTask: Exception: " + result.getMessage());
// TODO: decide what to do when there is an exception
} else {
Log.d(TAG, "SetupTask: startSearch()");
activityReference.get().startSearch();
}
}
}
Это код, который я получил от Pocketsphinx-android. Настройка ресурсов и распознавателя речи требует времени, поэтому они предложили сделать это в асинхронной задаче, чтобы предотвратить потерю кадров в основном потоке. Могу ли я сделать что-то очевидное, чтобы избавиться от этого предупреждения? Я протестировал синхронную версию этого кода, приведенную ниже, и получил ту же трассировку стека.
try {
Assets assets = new Assets(this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
startSearch();
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
Я закрепил это дальше, чтобы ..
File assetDir = assets.syncAssets();
потому что я изменил это на..
File assetDir = assets.getExternalDir()
и я не получил никакого предупреждения. Похоже на проблему Pocketsphinx-Android.
ОП уже ответил на свой вопрос, мой ответ - показать, почему syncAssets()
вызывает предупреждение logcat, а getExternalDir()
нет.
Согласно исходному коду PocketSphinx , syncAssets()
вызывает два внутренних метода: getItems() и getExternalItems(), оба из которых открываются InputStream
(последний открывается FileInputStream
).
Например, в getItems()
:
Reader reader = new InputStreamReader(openAsset(path + HASH_EXT));
openAsset()
:
private InputStream openAsset(String asset) throws IOException {
return assetManager.open(new File(SYNC_DIR, asset).getPath());
}
Вы получаете предупреждения из-за того, что встроенные InputStreams
не закрываются.
Да, это. Им следует переместить InputStream
на локальный объект и закрыть его после использования.
Так это баг Pocketsphinx-android?