Java StrictMode抱怨InputStream未关闭
我收到Android中的以下违规报告 02-05 04:07:41.190:错误/严格模式(15093):已获取资源 在附加的堆栈跟踪,但从未释放。有关详细信息,请参见java.io.Closeable 关于避免资源泄漏的信息。02-05 04:07:41.190: 错误/StrictMode(15093):java.lang.Throwable:显式终止 未调用方法“close” 它是在嘲笑没有正确关闭数据流。但是,在中关闭Java StrictMode抱怨InputStream未关闭,java,android,objectinputstream,android-strictmode,Java,Android,Objectinputstream,Android Strictmode,我收到Android中的以下违规报告 02-05 04:07:41.190:错误/严格模式(15093):已获取资源 在附加的堆栈跟踪,但从未释放。有关详细信息,请参见java.io.Closeable 关于避免资源泄漏的信息。02-05 04:07:41.190: 错误/StrictMode(15093):java.lang.Throwable:显式终止 未调用方法“close” 它是在嘲笑没有正确关闭数据流。但是,在中关闭是否应该关闭底层流?标记错误的原因可能是什么 private
是否应该关闭底层流?标记错误的原因可能是什么
private ArrayList<Uri> loadPath() {
ArrayList<Uri> uris = new ArrayList<Uri>();
if (mFile.exists()) {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new BufferedInputStream(
new FileInputStream(mFile), STREAM_BUFFER_SIZE));
ArrayList<String> strings = new ArrayList<String>();
strings.addAll((ArrayList<String>) in.readObject());
for (String string : strings) {
uris.add(Uri.parse(string));
}
} catch (Exception e) {
mFile.delete();
} finally {
IOUtils.closeQuietly(in);
}
}
return uris;
}
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
}
} catch (IOException ioe) {
// ignore
}
}
private ArrayList loadPath(){
ArrayList URI=新的ArrayList();
if(mFile.exists()){
ObjectInputStream in=null;
试一试{
in=新对象输入流(新的BufferedInputStream(
新文件输入流(mFile),流(缓冲区大小);
ArrayList字符串=新的ArrayList();
.readObject()中的strings.addAll((ArrayList);
for(字符串:字符串){
add(Uri.parse(string));
}
}捕获(例外e){
mFile.delete();
}最后{
安静地关闭(在);
}
}
返回URI;
}
公共静态输入(InputStream输入){
试一试{
如果(输入!=null){
input.close();
}
}捕获(ioe异常ioe){
//忽略
}
}
如果查看ObjectOutpuStream源代码,您将看到其close方法关闭底层流。Android的严格模式和许多其他代码分析工具一样存在误报,您可以忽略或重写代码,使其不会抱怨(内联关闭方法)。除非您使用的是ProGuard,它可能会对字节码造成一点麻烦,否则代码应该可以工作
FileInputStream
具有到CloseGuard
的钩子,如果实例已关闭,则会在finalize()中选中该钩子。这就是我认为它应该起作用的原因。问题是是否调用了天气close()
我认为FileInputStream
是创建的(因为StrictMode引发了异常),但最后抛出了一个异常,并在某个地方被忽略
try {
if (input != null) {
input.close();
}
} catch (Exception ioe) {
// check exception here
}
查看源代码,两个和的构造函数都可以抛出异常,这将导致在下一行分配FileInputStream
对象,但中的变量仍然为null:
in = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(mFile),
STREAM_BUFFER_SIZE)
);
由于当我们到达finally
块时,in
中的为空,因此打开的FileInputStream
对象将不会被closequitley()关闭(
方法关闭,导致stricmode
最终抱怨:)
我建议的最简单的修复方法是将该分配拆分为3个变量,并在每个变量上调用closequity()
,可能类似这样:
private ArrayList<Uri> loadPath() {
final ArrayList<Uri> uris = new ArrayList<Uri>();
if (mFile.exists()) {
ObjectInputStream ois = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(mFile);
bis = new BufferedInputStream(fis, STREAM_BUFFER_SIZE);
ois = new ObjectInputStream(bis);
final ArrayList<String> strings = new ArrayList<String>();
strings.addAll((ArrayList<String>) ois.readObject());
for (final String string : strings) {
uris.add(Uri.parse(string));
}
} catch (final Exception e) {
mFile.delete();
} finally {
closeQuietly(fis);
closeQuietly(bis);
closeQuietly(ois);
}
}
return uris;
}
private ArrayList loadPath(){
最终ArrayList URI=新ArrayList();
if(mFile.exists()){
ObjectInputStream ois=null;
FileInputStream fis=null;
BufferedInputStream bis=null;
试一试{
fis=新文件输入流(mFile);
bis=新的BufferedInputStream(fis,流\缓冲区\大小);
ois=新的ObjectInputStream(bis);
最终ArrayList字符串=新ArrayList();
strings.addAll((ArrayList)ois.readObject());
for(最终字符串:字符串){
add(Uri.parse(string));
}
}捕获(最终异常e){
mFile.delete();
}最后{
关闭(fis);
国际清算银行(bis);
(ois);
}
}
返回URI;
}
在此代码示例中,您只关闭ObjectInputStream
,而不关闭BufferedInputStream
或者FileInputStream
,您需要全部关闭它们。不确定StrictMode检查器有多智能,但它似乎被延迟关闭(即使用实用程序为您关闭流)弄糊涂了。在我的情况下,即使close()
内嵌在finally
子句中。Android的StrictMode不是代码分析工具。它是在源代码中实现的查看FileInputStream
和CloseGuard
中的finalize()
。很好地发现了这一点,但在我的例子中没有发生异常。(我会回去仔细检查一下,以确保绝对正确。)也许我错了,但你不也会抱怨“可能的情况”吗?例如,它抱怨来自主线程的IO访问,即使没有实际导致ANR。它应该抱怨实际发生的事情。在主线程上进行IO访问的情况下,主线程上确实发生了IO访问。(这不仅仅是理论上的。)因此,如果InputStream真的泄漏了,它应该只抱怨InputStream泄漏。如果你在OP的代码中发现了可能导致泄漏的真正问题,你就会得到赏金。我不是OP,我自己的代码非常相似,但有细微的不同,我仍然需要彻底了解它。谢谢!如果您也希望帮助您找出代码中的问题,那么从这里添加一个链接很可能会添加几组新的眼睛来查看它:)您呢?这与康斯坦丁·索洛马托夫的回答相矛盾。@GrahamBorland只需对其进行测试,您就会看到。
in = new ObjectInputStream(new BufferedInputStream(
new FileInputStream(mFile), STREAM_BUFFER_SIZE));