Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么exception.printStackTrace()被认为是不好的做法?_Java_Exception_Stack Trace_Printstacktrace - Fatal编程技术网

Java 为什么exception.printStackTrace()被认为是不好的做法?

Java 为什么exception.printStackTrace()被认为是不好的做法?,java,exception,stack-trace,printstacktrace,Java,Exception,Stack Trace,Printstacktrace,有很多证据表明,打印异常的堆栈跟踪是不好的做法 例如,从RegexpSingleline签入Checkstyle: 此检查可用于[…]查找常见的错误做法,例如调用ex.printStacktrace() 然而,我正在努力寻找一个合理的原因,因为堆栈跟踪在跟踪导致异常的原因时非常有用。我所知道的事情: 堆栈跟踪永远不应该对最终用户可见(出于用户体验和安全目的) 生成堆栈跟踪是一个相对昂贵的过程(尽管在大多数“例外”情况下不太可能成为问题) 许多日志框架将为您打印堆栈跟踪(我们的没有,也没有,我

有很多证据表明,打印异常的堆栈跟踪是不好的做法

例如,从RegexpSingleline签入Checkstyle:

此检查可用于[…]查找常见的错误做法,例如调用ex.printStacktrace()

然而,我正在努力寻找一个合理的原因,因为堆栈跟踪在跟踪导致异常的原因时非常有用。我所知道的事情:

  • 堆栈跟踪永远不应该对最终用户可见(出于用户体验和安全目的)

  • 生成堆栈跟踪是一个相对昂贵的过程(尽管在大多数“例外”情况下不太可能成为问题)

  • 许多日志框架将为您打印堆栈跟踪(我们的没有,也没有,我们无法轻松更改)

  • 打印堆栈跟踪不构成错误处理。它应该与其他信息记录和异常处理相结合


  • 避免在代码中打印堆栈跟踪还有哪些其他原因?

    第一件事printStackTrace()并不像您所说的那样昂贵,因为堆栈跟踪是在异常本身创建时填充的


    其思想是通过记录器框架传递任何进入日志的内容,以便可以控制日志记录。因此,不要使用printStackTrace,只需使用类似于
    Logger.log(msg,exception)的东西

    在服务器应用程序中,stacktrace会放大stdout/stderr文件。它可能变得越来越大,充满了无用的数据,因为通常您没有上下文,也没有时间戳等等


    e、 g.catalina.out当使用tomcat作为容器时

    printStackTrace()
    打印到控制台。在生产环境中,从来没有人在观看。Suraj是正确的,应将此信息传递给记录器

    您在这里涉及到多个问题:

    1) 堆栈跟踪永远不能让最终用户看到(出于用户体验和安全目的)

    是的,应该可以访问它来诊断最终用户的问题,但最终用户不应该看到它们,原因有两个:

    • 它们非常模糊和不可读,应用程序看起来对用户非常不友好
    • 向最终用户显示堆栈跟踪可能会带来潜在的安全风险。如果我错了,请纠正我,PHP实际上会在堆栈跟踪中打印函数参数-非常棒,但非常危险-如果您在连接到数据库时遇到异常,您可能会在堆栈跟踪中看到什么

    2) 生成堆栈跟踪是一个相对昂贵的过程(尽管在大多数“异常”情况下不太可能成为问题)

    生成堆栈跟踪是在创建/抛出异常时发生的(这就是为什么抛出异常要付出代价),打印并没有那么昂贵。事实上,您可以在自定义异常中重写
    Throwable#fillInStackTrace()
    ,从而有效地使抛出异常几乎与简单的GOTO语句一样便宜

    3) 许多日志框架将为您打印堆栈跟踪(我们的没有,也没有,我们无法轻松更改)

    很好。这里的主要问题是:如果框架为您记录异常,则什么也不做(但确保它做!)如果您想自己记录异常,请使用类似于或的日志框架,不要将它们放在原始控制台上,因为很难控制它

    使用日志框架,您可以轻松地将堆栈跟踪重定向到文件、控制台,甚至将它们发送到指定的电子邮件地址。使用硬编码的
    printStackTrace()
    您必须使用
    sysout

    4) 打印堆栈跟踪不构成错误处理。它应该与其他信息记录和异常处理相结合

    再次:正确地记录
    SQLException
    (使用日志框架,使用完整的堆栈跟踪)并显示nice:“抱歉,我们当前无法处理您的请求”消息。你真的认为用户对原因感兴趣吗?你看到StackOverflow错误屏幕了吗?这很幽默,但没有透露任何细节。但是,它可以确保用户对问题进行调查

    但是他会马上打电话给你,你需要能够诊断出问题。因此,您需要两者:正确的异常日志记录和用户友好的消息



    总结:始终记录异常(最好使用),但不要向最终用户公开它们。仔细考虑GUI中的错误消息,仅在开发模式下显示堆栈跟踪。

    打印异常的堆栈跟踪本身并不构成不好的做法,但仅在异常发生时打印stace跟踪可能是这里的问题——通常情况下,仅打印堆栈跟踪是不够的

    此外,如果在
    catch
    块中执行的所有操作都是
    e.printStackTrace
    ,则有可能怀疑没有执行正确的异常处理。不正确的处理最多可能意味着忽略了一个问题,最坏可能意味着程序继续在未定义或意外状态下执行

    示例

    我们考虑下面的例子:

    try {
      initializeState();
    
    } catch (TheSkyIsFallingEndOfTheWorldException e) {
      e.printStackTrace();
    }
    
    continueProcessingAssumingThatTheStateIsCorrect();
    
    在这里,我们想先进行一些初始化处理,然后再继续进行一些需要进行初始化的处理

    在上面的代码中,应该捕获并正确处理异常,以防止程序继续进行
    连续处理,假设我们认为状态正确的方法会导致问题

    在许多情况下,
    e.printStackTrace()
    表示某些异常正在被吞噬,并且允许处理继续进行,就好像没有任何问题发生一样

    为什么这会成为一个问题?try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
        try {
          // do stuff
        } catch (Exception e) {
            e.printStackTrace(); // and swallow the exception
        }