log4j没有打印异常的stacktrace

时间:2010-02-19 08:55:55

标签: java tomcat logging log4j

我正在使用log4j和tomcat。当我在JSP中记录异常时,servlet:

private Logger _log = Logger.getLogger(this.getClass());
...
try{...} catch (Exception e) {
    _log.error("Error refreshing all prices", e);
}

我只获得异常的第一行,没有堆栈跟踪。

  

17-Feb 17:37:45 ERROR AutoContrib:175 - 发布csv文件时出现异常:   java.lang.ArrayIndexOutOfBoundsException

根本没有帮助!

我的log4j.properties文件(/tomcat/common/classes/log4j.properties)如下所示:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.stdout.threshold=info

log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.maxFileSize=5000KB
log4j.appender.file.maxBackupIndex=10
log4j.appender.file.File=${catalina.home}/logs/web.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.file.threshold=info

log4j.rootLogger=debug, stdout, file

8 个答案:

答案 0 :(得分:72)

实际上,这可能是由于热点优化:在抛出一定数量的相同异常后,它会停止打印出跟踪。可以使用VM arg关闭此功能,请参阅:

来自http://www.oracle.com/technetwork/java/javase/relnotes-139183.html

  

服务器VM中的编译器现在提供正确的堆栈回溯   对于所有“冷”内置异常。出于性能目的,何时   抛出这样的异常几次,该方法可能会被重新编译。   重新编译后,编译器可以选择更快的策略使用   预分配的异常,不提供堆栈跟踪。要禁用   完全使用预分配的异常,使用这个新标志:   -XX:-OmitStackTraceInFastThrow

更多信息:

http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-to-lose-their-stack-traces-in-production-and-the-fix/

答案 1 :(得分:20)

您发布的内容应显示javadoc中所述的堆栈跟踪。

请注意,如果您不包含消息(并且只调用logger.error(ex)),则不会记录堆栈跟踪。

答案 2 :(得分:15)

错误方法有两种重载方法。

  1. logger.error(ex);
  2. logger.error("some oops string ", ex);
  3. 如果您使用1st方法,它只会打印Exception的名称。 如果你使用第二种方法,一些消息和异常将打印完整的堆栈跟踪,类似于e.printStackTrace()方法。

答案 3 :(得分:6)

上面的@Luhar回答说,我在同样的事情上挣扎,最后这对我有用; 这种方法的好处是我们不必修改像JVM,Log4J这样的系统级设置,因为我们从来不知道它可能会带来新的意外惊喜!

try {

...
..

} catch (Exception er) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        er.printStackTrace(new PrintStream(os));
        LOGGER.error(new String(os.toByteArray()));
        //LOGGER.error(er);
}

答案 4 :(得分:1)

我认为您的配置没有任何问题,因此请尝试将log4j升级到较新版本(不一定是最新版本)。

虽然在这种情况下不是问题,但您最好制作记录器private static final

答案 5 :(得分:1)

我没有使用fillStackTrace调用,所以我无法评论是否可行。另一种方法是使用一个从异常中返回格式化文本的小方法。

public static String getStackTrace(Exception e)
{
    StringWriter sWriter = new StringWriter();
    PrintWriter pWriter = new PrintWriter(sWriter);
    e.printStackTrace(pWriter);
    return sWriter.toString();
}

在您的日志记录代码中,您可以写:

logger.error("An exception occurred: " + Utils.getStackTrace(e));

答案 6 :(得分:0)

您可以在catch块中添加这些代码行。

catch (SQLException e) {
            CharArrayWriter cw = new CharArrayWriter();
            PrintWriter w = new PrintWriter(cw);
            e.printStackTrace(w);
            w.close();
            String trace = cw.toString();

    log.error("This is complete stacktrace", trace);
}

答案 7 :(得分:-1)

使用您的代码示例:

private static final Logger _log = Logger.getLogger(MyClass.class);
...
try{...} catch (Exception e) {
    //Change
    //_log.error("Error refreshing all prices", e);

   //To
    _log.error("Error refreshing all prices", e.fillInStackTrace());
}

您将看到显示所有堆栈跟踪。

PS。在声明public class MyClass {

之后,让Logger成为单身...(检查我的声明)