我的Android代码表现得很有趣。输入流应该并且确实抛出IOException,这正确地导致控制转到// read an error stream
。正确读取错误流,调试器将步骤return error_message
,error_message
变量包含从错误流中读取的预期字符。然后它会正确地转到// no op
块中的finally
,我只是为了踢而添加。
然后,它走到return "all hope lost";
!!然后,不再返回调用者,而是进入某些Android系统代码,该代码会抛出SecurityException
,其中包含缺少内容权限的消息。
删除finally
块没有影响 - 错误仍然存在。正在读取的流来自HTTP URL连接。如果服务器返回200
没有问题但是如果服务器返回400
它会经历上面描述的奇怪路径并尝试抛出奇怪的SecurityException。
try {
// read an input stream into message
return message;
} catch (IOException outer) {
try {
// read an error stream into error_message
return error_message;
} catch (IOException inner) {
return "all hope lost";
}
} finally {
// no op, just to step debugger
}
更新:发布确切的代码和调试跟踪。
try {
/*x*/ BufferedReader buffered_reader =
new BufferedReader(
new InputStreamReader(
new BufferedInputStream(http_url_connection.getInputStream())));
StringBuilder string_builder = new StringBuilder();
String line;
for (line = buffered_reader.readLine();
line != null;
line = buffered_reader.readLine()) {
string_builder.append(line);
}
return string_builder.toString();
} catch (IOException io_exception) {
this.io_exception = io_exception;
BufferedReader buffered_reader =
new BufferedReader(
new InputStreamReader(
new BufferedInputStream(http_url_connection.getErrorStream())));
StringBuilder string_builder = new StringBuilder();
try {
for (String line = buffered_reader.readLine();
line != null;
line = buffered_reader.readLine()) {
string_builder.append(line);
}
/*y*/ String error_message = "server error: " + string_builder.toString();
return error_message;
} catch (IOException exception) {
String level_2_error_message = "level 2 error: " + exception.getMessage();
return level_2_error_message;
} finally {
return "foo";
}
}
行/*x*/
会导致按预期跳转到第一个catch
。然后按预期执行最多/*y*/
的所有行。然后,奇怪的事情就是行/*y*/
没有完成,如果没有catch
或者{{{},则会立即控制下一个finally
块1}}。如果有finally
则不会获得最后一个finally
阻止。
catch
行上字符串缓冲区的内容看起来很完美 - 来自服务器的20个字符的字符串。
答案 0 :(得分:1)
你说线/* y */
通过阅读该行代码,以下是合理的解释:
例外是NullPointerException
,因为string_builder
是null
。但它不可能。
例外是OutOfMemoryError
,因为您没有足够的可用空间来toString()
调用来创建新的String
对象。
StringBuilder
可能不是java.lang.StringBuilder
,而是您自己写的一些课程。在这种情况下,任何例外都是可能的。
但是,我看不出你将如何在第二个IOException
处理程序中结束。
除此之外,唯一的其他可能的解释是该源代码与您实际执行的代码不匹配;例如你忘了重新编译某些内容,或者在上次编译后忘了重新部署。
值得一提的是,return
中的finally
几乎肯定是错误的。
这意味着您将返回"foo"
而不是任何一条错误消息。
如果(例如)string_builder.toString()
确实抛出了NPE或OOME,那么return
会挤压它。
finally
return
可能会有非直观的行为。肯定不是你应该做的“调试”!!!