Java log4j 不打印异常的堆栈跟踪
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2295015/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
log4j not printing the stacktrace for exceptions
提问by Ryan
I am using log4j with tomcat. When I log exceptions in my JSPs, servlets:
我在 tomcat 中使用 log4j。当我在 JSP 中记录异常时,servlet:
private Logger _log = Logger.getLogger(this.getClass());
...
try{...} catch (Exception e) {
_log.error("Error refreshing all prices", e);
}
I only get the first line of the exception, without a stacktrace.
我只得到异常的第一行,没有堆栈跟踪。
17-Feb 17:37:45 ERROR AutoContrib:175 - Exception while publishing csv file: java.lang.ArrayIndexOutOfBoundsException
2 月 17 日 17:37:45 错误 AutoContrib:175 - 发布 csv 文件时出现异常:java.lang.ArrayIndexOutOfBoundsException
Not very helpful at all!
一点帮助都没有!
My log4j.properties file (/tomcat/common/classes/log4j.properties) looks like this:
我的 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
采纳答案by minimo
Actually, it's probably due to a hotspot optimization: after a certain number of the same exception being thrown it stops printing out trace. This can be turned off with a VM arg, see:
实际上,这可能是由于热点优化:在抛出一定数量的相同异常后,它停止打印跟踪。这可以通过 VM arg 关闭,请参阅:
From http://www.oracle.com/technetwork/java/javase/relnotes-139183.html:
来自http://www.oracle.com/technetwork/java/javase/relnotes-139183.html:
The compiler in the server VM now provides correct stack backtraces for all "cold" built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow.
服务器 VM 中的编译器现在为所有“冷”内置异常提供正确的堆栈回溯。出于性能考虑,当多次抛出此类异常时,可能会重新编译该方法。重新编译后,编译器可以使用不提供堆栈跟踪的预分配异常选择更快的策略。要完全禁用预分配异常,请使用此新标志:-XX:-OmitStackTraceInFastThrow。
More here:
更多在这里:
回答by Buhake Sindi
Using your code sample:
使用您的代码示例:
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());
}
You'll see all the stack trace displayed.
您将看到显示的所有堆栈跟踪。
PS. Make Logger a singleton...(check my declaration) just after declaring public class MyClass {
附注。在声明之后使 Logger 成为单例......(检查我的声明)public class MyClass {
回答by Bozho
I don't see anything wrong with your config, so try to upgrade log4j
to a newer (not necessarily the latest) version.
我没有发现您的配置有任何问题,因此请尝试升级log4j
到更新的(不一定是最新的)版本。
Though not the problem in this case, you'd better make your loggers private static final
虽然在这种情况下不是问题,但你最好让你的记录器 private static final
回答by Luhar
I haven't used the fillStackTrace call, so I cannot comment if that will work. Another approach is to use a little method that returns the formatted text from an Exception.
我没有使用过 fillStackTrace 调用,所以我无法评论这是否有效。另一种方法是使用一个小方法从异常返回格式化文本。
public static String getStackTrace(Exception e)
{
StringWriter sWriter = new StringWriter();
PrintWriter pWriter = new PrintWriter(sWriter);
e.printStackTrace(pWriter);
return sWriter.toString();
}
In your logging code, you could write:
在您的日志记录代码中,您可以编写:
logger.error("An exception occurred: " + Utils.getStackTrace(e));
回答by objects
回答by Rockoder
Like answered by @Luhar above, I struggled with same thing and finally this worked for me; Good thing about this approach is we don't have to tinker with system level settings like JVM, Log4J since we never know it may lead to new unexpected surprise !
就像上面@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);
}
回答by madhu
You can add these lines of code in your catch block.
您可以在 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);
}
回答by Venkatesh Boya
There are two overloaded methods for error method.
error 方法有两种重载方法。
logger.error(ex);
logger.error("some oops string ", ex);
logger.error(ex);
logger.error("some oops string ", ex);
if you use 1st method , which will only print the name of the Exception.
if you use 2nd method, some message along with exception which will print complete stack trace similar to e.printStackTrace()
method.
如果您使用第一种方法,它只会打印异常的名称。如果您使用第二种方法,一些消息和异常将打印类似于e.printStackTrace()
方法的完整堆栈跟踪 。