【问题标题】:Java error: New exception is thrown in catch block, original stack trace may be lostJava 错误:在 catch 块中抛出新异常,原始堆栈跟踪可能会丢失
【发布时间】:2011-06-21 04:54:38
【问题描述】:
try {
    // code which throws exception.
} catch (SQLException sqlex) {
    logger.error("Custom message", sqlex);
    **throw new CustomApplicationException("Custom message", sqlex);**
}

在上面的例子中,在粗体线上,我收到 PMD 错误,因为“在 catch 块中抛出了新异常,原始堆栈跟踪可能会丢失”。我知道这个问题已经被问过很多次了,也有很多在线参考资料可供参考。我已经尝试了所有可能的方法。但我仍然无法删除此 PMD 错误。请让我知道这个代码片段有什么问题。 提前致谢!

【问题讨论】:

  • 这是如何解决的?

标签: java exception pmd rethrow


【解决方案1】:

我认为该代码没有任何问题。

但我也认为 PMD 不会/应该为该代码提供该错误。 IIRC,你会得到这样的错误:

try {
    // code which throws exception.
} catch (SQLException sqlex) {
    throw new CustomApplicationException("Custom message");  // no cause!
}

您可能拥有旧版本的 PMD,或者有人一直在“改进”您正在使用的 PMD 规则。

【讨论】:

  • 我认为你是对的。这是一个 findbugs 错误。堆栈跟踪不会丢失。
【解决方案2】:

需要修改异常类如下以保留原始堆栈跟踪

try {
    // code which throws exception.
} catch (SQLException sqlex) {
    throw new CustomApplicationException("Any Message", sqlex);
}

CustomApplicationException.java

public class CustomApplicationException extends RuntimeException {

  public CustomApplicationException() {
  }

  public CustomApplicationException(String message) {
    super(message);
  }

  public CustomApplicationException(String message, Throwable cause) {
    super(message, cause);
  }

}

【讨论】:

    【解决方案3】:

    需要抛出已经触发的异常:

    try {
            // code which throws exception.
        } catch (SQLException sqlex) {
            /* You can show a specific log here (See below) */
            throw sqlex;
        }
    

    如果要显示特定日志,可以使用记录器:

    /* Use this imports */
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    ...
    /* Declare as global variable */
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    public Logger getLogger() {
        return logger;
    }
    public void setLogger(Logger logger) {
        this.logger = logger;
    }
    /* Use in any place */
    logger.error(" an error ");
    logger.trace(" operational trace ");
    logger.debug(" specific trace for debugging ");
    

    如果您使用的是 Maven,请在您的 pom.xml 中声明:

        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-simple</artifactId>
                    <version>1.5.2</version>
                    <scope>provided</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    

    【讨论】:

      【解决方案4】:

      代码检查器是解决问题的好工具。但是在这种情况下,您的代码很好,并且 PMD 可能过度保护。检查 PMD 中有关错误的文档,看看是否还有其他需要考虑的问题。然后,如果您仍然对您的代码感到满意,您可以添加一个 //NOPMD 标记以让 PMD 忽略该行。我不记得这是自动的还是您必须配置 PMD 才能查找 //NOPMD。

      请注意,这样的 PMD 检查的内联异常也不是真正推荐的,当然也不应该被视为最佳实践。但是对于像 PMD 这样的代码检查器,偶尔会出现一些你想忽略的标志。

      【讨论】:

        【解决方案5】:

        您使用的是哪个版本的 PMD?您可能会看到在较新版本中修复的false positive。 (该链接仅指向一个修复了此类误报的地方。可能不止一个。)

        根据您使用的 Java 版本以及在 catch 块中抛出另一个异常的确切方式,确实有可能丢失完整的堆栈跟踪信息。如果您使用的是最新的 PMD 版本并收到此投诉,您可能希望在 sourceforge 页面上报告 PMD 错误,然后按照其他人所说的那样暂时禁用该投诉的特定实例。

        【讨论】:

          【解决方案6】:

          我有同样的问题,我们忽略了 pmd 配置文件中的 PMD 问题,如下所示。

          <?xml version="1.0" encoding="UTF-8"?>
          <description>Custom Rulesets for production code</description>
          <exclude-pattern>.*/src/test/java/.*</exclude-pattern>
          <ruleset xmlns="http://pmd.sourceforge.net/ruleset/5.5.3">    
          <rule ref="category/java/bestpractices.xml/PreserveStackTrace">
                  <exclude name="PreserveStackTrace"/>
              </rule>
          </ruleset>
          

          我们使用maven,所以在maven插件中使用了这个配置文件。

          参考:https://pmd.github.io/pmd-6.0.1/pmd_rules_java_bestpractices.html#preservestacktrace

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-08-02
            • 2010-11-09
            • 2014-08-09
            • 1970-01-01
            • 2023-03-19
            • 2016-04-27
            • 2019-05-04
            相关资源
            最近更新 更多