Java错误:在catch块中抛出新异常,原始堆栈跟踪可能丢失。

7
try {
    // code which throws exception.
} catch (SQLException sqlex) {
    logger.error("Custom message", sqlex);
    **throw new CustomApplicationException("Custom message", sqlex);**
}

在上面的例子中,在加粗的那一行,我收到了PMD错误提示:“在catch块中抛出新异常,原始堆栈跟踪可能会丢失”。我知道这个问题已经被问过很多次,也有很多在线参考资料可供使用。我尝试了所有可能的方法,但仍然无法消除这个PMD错误。请告诉我这段代码有什么问题。 提前感谢您!

这个问题是如何解决的? - Akshay Hazari
6个回答

6

我认为这段代码没有问题。

但是,我也不认为PMD会/应该因为这段代码而报错。如果我没记错的话,你会在以下情况下收到这个错误:

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

可能您使用的是旧版PMD,或者有人已经对您正在使用的PMD规则进行了“改进”。


我认为你是正确的。这是一个FindBugs错误。堆栈跟踪不会丢失。 - Christian Kuetbach

3
需要修改异常类以保留原始堆栈跟踪。
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);
  }

}

1

代码检查器是发现问题的好工具。然而,在这种情况下,您的代码很好,PMD可能过于保护。请查看PMD中有关错误的文档,并查看是否还有其他需要考虑的内容。然后,如果您对自己的代码仍然满意,可以添加//NOPMD标记以使PMD忽略该行。我不记得这是否是自动的,或者您必须配置PMD来查找//NOPMD。

请注意,像这样内联异常到PMD检查并不是真正推荐的做法,当然也不应视为最佳实践。但是,使用像PMD这样的代码检查器时,会有偶尔想要忽略某些原因的标志。


0

我也遇到了同样的问题,我们可以像下面这样,在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


0
你使用的PMD版本是什么?你可能会看到一个false positive,这在更新版本中已经修复。(链接只是其中一个修复此类误报的地方。可能有多个。)
根据你使用的Java版本以及在catch块中如何抛出另一个异常,确实可能会丢失完整的堆栈跟踪信息。如果你正在使用最新的PMD版本并且收到此投诉,请在sourceforge页面上报告PMD错误,然后暂时禁用该投诉的特定实例,就像其他人所说的那样。

-1

需要抛出已触发的异常:

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

如果您想显示特定的日志,可以使用记录器(logger):
/* 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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接