I want to read the full stack trace of an exception that I capture.
For example:
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.ibm.db2.jcc.DB2Driver'
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1136)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
at com.azurian.lce.usuarios.ConnectionManager.getConnection(ConnectionManager.java:65)
at com.azurian.lce.usuarios.db2.UsuarioDAOImpl.autenticar(UsuarioDAOImpl.java:101)
at com.azurian.lce.usuarios.UsuarioServiceImpl.autenticar(UsuarioServiceImpl.java:31)
at com.azurian.lce.web.admin.actions.LoginAction.execute(LoginAction.java:49)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: COM.ibm.db2.jcc.DB2Driver
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.开发者_开发知识库forName(Unknown Source)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1130)
... 23 more
I want to read the "... 23 more" to see where the exception comes from.
BalusC is right. See here: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html#printStackTrace()
In particular:
Note the presence of lines containing the characters "...". These lines indicate that the remainder of the stack trace for this exception matches the indicated number of frames from the bottom of the stack trace of the exception that was caused by this exception (the "enclosing" exception). This shorthand can greatly reduce the length of the output in the common case where a wrapped exception is thrown from same method as the "causative exception" is caught.
What this means in your example is that:
BasicDataSource.java
line 1136 caught the ClassNotFoundException
thrown on line 1130 and reraised it as a SQLNestedException
. Hence the remainder of the stacktrace for the ClassNotFoundException
matches the SQLNestedException above and the stacktrace is printed in this more concise format.
The answer is simple, those lines are already in the stacktrace :)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
at com.azurian.lce.usuarios.ConnectionManager.getConnection(ConnectionManager.java:65)
at com.azurian.lce.usuarios.db2.UsuarioDAOImpl.autenticar(UsuarioDAOImpl.java:101)
at com.azurian.lce.usuarios.UsuarioServiceImpl.autenticar(UsuarioServiceImpl.java:31)
at com.azurian.lce.web.admin.actions.LoginAction.execute(LoginAction.java:49)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)
Basically, the following is happening in BasicDataSource#createDataSource()
:
try {
Class.forName(driverClassName); // Line 1130
} catch (ClassNotFoundException e) {
throw new SQLNestedException(e, "Cannot load JDBC driver class '" + driverClassName + "'"); // Line 1136
}
When the outer exception (SQLNestedException) wraps the inner exception (ClassNotFoundError) they are on the same thread, and so share a common base to their stack trace.
The (23 more...) shows where that common stack starts for the inner exception, which is also the place where the outer exception was thrown. So, whenever you see (XX more...), just look to the exception above to see the rest of the stack trace.
If you want to programmatically print out the stacktrace without the ellipsis for common traces, then you can use Throwable.getStackTrace() and print out all the elements yourself.
Try this out. This logic loops through the main exception and all the causes of it, till there is no more cause (cause == null
) left to process. This way you can avoid the 23 more... message. I have not yet tested this yet, but i believe this should work out for you.
BTW - logWriter is a buffered writer. You may want to use System.out.print or any other logging API.
public static void debugError(final String message, final Throwable th) {
final String logMessage = "[ERROR] - " + message;
try {
logWriter.write(logMessage);
logWriter.newLine();
// dump exception stack if specified
if (null != th) {
final StackTraceElement[] traces = th.getStackTrace();
if (null != traces && traces.length > 0) {
logWriter.write(th.getClass() + ": " + th.getMessage());
logWriter.newLine();
for (final StackTraceElement trace : traces) {
logWriter.write(" at " + trace.getClassName() + '.' + trace.getMethodName() + '(' + trace.getFileName() + ':' + trace.getLineNumber() + ')');
logWriter.newLine();
}
}
Throwable cause = th.getCause();
while (null != cause) {
final StackTraceElement[] causeTraces = cause.getStackTrace();
if (null != causeTraces && causeTraces.length > 0) {
logWriter.write("Caused By:");
logWriter.newLine();
logWriter.write(cause.getClass() + ": " + cause.getMessage());
logWriter.newLine();
for (final StackTraceElement causeTrace : causeTraces) {
logWriter.write(" at " + causeTrace.getClassName() + '.' + causeTrace.getMethodName() + '(' + causeTrace.getFileName() + ':' + causeTrace.getLineNumber() + ')');
logWriter.newLine();
}
}
// fetch next cause
cause = cause.getCause();
}
}
} catch (final IOException ex) {
System.err.println(logMessage);
if (null != th) {
th.printStackTrace();
}
}
}
精彩评论