在 java 异常处理中,记录异常堆栈信息最直接的方法是使用 printstacktrace() 方法,或者通过 exceptionutils.getstacktrace() 工具类获取字符串。调用这些方法会将异常的完整堆栈轨迹输出到标准错误流或转换为字符串,从而保留引发异常的代码路径、行号及嵌套原因。

如何捕获并打印异常堆栈
使用 try-catch 块捕获异常后,直接调用 ex.printStackTrace() 即可将堆栈信息打印到控制台。这是最基础的调试手段,无需额外依赖,但仅适用于开发环境或临时排查。

import java.io.IOException;
public class StackTraceDemo {
public static void main(String[] args) {
try {
divide(10, 0);
} catch (ArithmeticException e) {
System.out.println("捕获到异常:" + e.getMessage());
e.printStackTrace(); // 打印完整堆栈到 stderr
}
}
private static int divide(int a, int b) {
return a / b; // 第14行触发异常
}
}
运行上述代码,控制台会输出类似如下的堆栈跟踪:
java.lang.ArithmeticException: / by zero at com.example.StackTraceDemo.divide(StackTraceDemo.java:14) at com.example.StackTraceDemo.main(StackTraceDemo.java:9)
其中第一行为异常类型和消息,后续每行表示一个调用帧,包含类名、方法名、文件名和行号。这种格式便于开发者快速定位问题源头。
如何将堆栈信息转为字符串
若需将堆栈信息存入日志文件或数据库,可借助 Apache Commons Lang 的 ExceptionUtils.getStackTrace() 方法,或将 printStackTrace() 的输出重定向至 StringWriter。前者更简洁,后者无外部依赖。

import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
public class StackToStringDemo {
public static void main(String[] args) {
try {
throw new RuntimeException("测试异常");
} catch (RuntimeException e) {
// 方式一:使用 Commons Lang
String stackTraceStr = ExceptionUtils.getStackTrace(e);
System.out.println("Commons Lang 方式:\n" + stackTraceStr);
// 方式二:手动 StringWriter
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
System.out.println("StringWriter 方式:\n" + sw.toString());
}
}
}
两种方式均返回包含完整堆栈信息的字符串,可直接用于日志记录。推荐使用 Commons Lang 方式,因其内部实现稳定且兼容性好;若无第三方库,则用 StringWriter 替代。
异常链中如何保留根因堆栈
当异常被包装时(如抛出新的 BusinessException 并传入原始异常),必须确保新异常构造函数接收了原始异常作为 cause,否则堆栈链断裂,无法追溯根本原因。调用 getCause() 可逐层获取嵌套异常及其堆栈。
以下代码演示正确包装异常以保留堆栈链:
import java.sql.SQLException;
public class CauseChainDemo {
public static void main(String[] args) {
try {
doDatabaseOperation();
} catch (SQLException e) {
// 正确做法:将原始异常作为 cause 传入
throw new RuntimeException("数据库操作失败", e);
}
}
private static void doDatabaseOperation() throws SQLException {
throw new SQLException("连接超时");
}
}
此时,外层 RuntimeException 的 printStackTrace() 会显示两层堆栈:外层异常本身的位置,以及内层 SQLException 的原始位置。若省略 e 参数,则内层堆栈丢失,仅保留包装点信息,不利于根因分析。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











