可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am using log4j with tomcat. When I log exceptions in my JSPs, servlets:
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
Not very helpful at all!
My log4j.properties file (/tomcat/common/classes/log4j.properties) looks like this:
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
回答1:
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:
From 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.
More here:
http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-to-lose-their-stack-traces-in-production-and-the-fix/
回答2:
What you have posted should display the stack trace as stated in the javadoc.
Note that if you don't include a message (and just call logger.error(ex)
) then the stack trace is not logged.
回答3:
There are two overloaded methods for error method.
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.
回答4:
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 !
try {
...
..
} catch (Exception er) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
er.printStackTrace(new PrintStream(os));
LOGGER.error(new String(os.toByteArray()));
//LOGGER.error(er);
}
回答5:
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.
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));
回答6:
I don't see anything wrong with your config, so try to upgrade log4j
to a newer (not necessarily the latest) version.
Though not the problem in this case, you'd better make your loggers private static final
回答7:
You can add these lines of code in your catch block.
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);
}
回答8:
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 {