每次我测试我的应用程序时,我都会在我的logcat中收到一次此警告.

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();
            }
        }
    }

这是我从pocketphinsx-android获得的代码. 设置Asset和语音识别器需要时间,因此他们建议在Asmat任务中执行,以防止主线程上丢失帧. 我可以做一些明显的事情来消除这个警告吗? 我在下面测试了此代码的同步版本,并生成了相同的堆栈跟踪.

  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()

而且我没有收到任何警告. 似乎是一个袖珍狮身电脑的问题.

推荐答案

OP已经回答了他自己的问题,我的答案是解释为什么syncAssets()会导致logcat警告,而getExternalDir()不会.

按照PocketSphinx sourcesyncAssets()调用两个内部方法,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());
}

由于inline InputStreams未关闭,您会收到警告.

Java相关问答推荐

如何在Java中使用Rest模板通过查询参数发送GET请求

无法从Spring Boot应用程序连接到SQL Docker服务器

使用json参数通过单击jSP文件中的按钮来运行server时出现问题

如何在Spring Boot中创建500错误的响应正文?

虚拟线程似乎在外部服务调用时阻止运营商线程

Java模式匹配记录

使用动态ID从json获取详细信息的Jolt规范

上下文初始化期间遇到异常-使用Java配置配置HibernateTemplate Bean时

将不受支持的时区UT重写为UTC是否节省?

try 创建一个对象,使用它,然后使用一条语句将其存储为列表

Chunk(Int)已弃用并标记为要删除

无法了解Java线程所消耗的时间

如何使用SpringBoot中的可分页对整数作为字符串存储在数据库中时进行排序

如何使用Jackson将XML元素与值和属性一起封装

有没有办法知道在合并中执行了什么操作?

Oracle中从JSON中提取和插入数据

持续时间--为什么在秒为负数的情况下还要做额外的工作?

Java 17与Java 8双重表示法

Java System.getProperty在哪里检索user.home?

如何在JSP中从select中获取值并将其放入另一个select