【问题标题】:Catching Same IOException Inside Catch IOException Block在 Catch IOException 块中捕获相同的 IOException
【发布时间】:2014-10-09 05:59:37
【问题描述】:

我的 Android 代码的行为很有趣。输入流应该并且确实会引发 IOException,这会正确地导致控制权转到// read an error stream。错误流被正确读取,调试器使用包含从错误流读取的预期字符的error_message 变量进入return error_message。然后它会正确地跳转到finally 块中的// no op,我添加它只是为了好玩。

然后,它会跳转到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*/ 行没有完成,如果没有finallyfinally,控制立即转到下一个catch 块。如果有 finally 则不会获得最后一个 catch 块。

/*y*/ 行上的字符串缓冲区的内容看起来非常好——来自服务器的 20 个字符的字符串。

【问题讨论】:

  • 你确实意识到,你可以做一些像Log.e(this.getClass().getSimpleName(), "Error in method insertMethodNameHere()", exception); 这样的事情,而不是这种疯狂的尝试,这样你就知道出了什么问题,对吧?
  • @Zhuinden 不是为了调试。异常来自网络连接,并且可能在用户在现场使用应用程序时发生。所以我看不出Log.e(...) 会有什么帮助。
  • 如果在最后一个块中放置一个 return 语句,行为仍然是一样的吗?
  • @eldjon 是的,还是一样。但我对这个问题有更新。发布确切的代码和跟踪。
  • 如果不知道实际的错误,就很难找到原因。

标签: java android exception try-catch ioexception


【解决方案1】:

你说/* y */行抛出异常

通过阅读那行代码,以下是合理的解释:

  • 例外是NullPointerException,因为string_buildernull。但不可能。

  • 例外是OutOfMemoryError,因为您没有足够的可用空间来调用toString() 来创建新的String 对象。

  • StringBuilder 可能不是java.lang.StringBuilder,而是您自己编写的某个类。在这种情况下,任何例外都是可能的。

但是,我看不出你会如何在第二个 IOException 处理程序中结束。


除此之外,唯一的其他可能解释是该源代码与您实际执行的代码不匹配;例如您忘记重新编译某些内容,或者在上次编译后忘记重新部署。


对于它的价值,您的return 中的finally 几乎可以肯定是一个错误。

  • 这意味着您将返回"foo",而不是任何一条错误消息。

  • 如果(例如)string_builder.toString() 确实抛出了 NPE 或 OOME,那么 return压制它。

带有returnfinally 可能具有非直觉行为。这当然不是你应该为“调试”而做的事情!!!

【讨论】:

  • +1 感谢您的建议。就 NPE 和 OOME 而言,stringbuilder 非常好。我穿过它。是的,return "foo" 是错误的。我尝试了有无。将在更多调查后更新。
猜你喜欢
  • 2012-11-02
  • 1970-01-01
  • 2015-01-29
  • 1970-01-01
  • 2012-12-19
  • 2018-02-10
  • 2011-03-14
  • 2012-10-18
  • 2017-12-12
相关资源
最近更新 更多