Java 异常中 e.getMessage() 和 e.toString() e.printStackTrace()的区别
一、概述
在java异常体系中,要打印异常信息,可以通过:e.getMessage() 、 e.toString() e.printStackTrace() 等方法打印出 一些 异常信息。已知的是这些方法都可以打印异常信息,但是这些方法打印的异常信息 都不相同,那么问题来啦: 这些方法打印异常信息的区别是?日常开发工作中,该用哪个方法打印异常信息呢?
二、代码理解
1、 Junit 单元测试 --- 模拟异常信息输出
@Test
public void test(){int num = 0 ;try {int i = 3/num ;} catch (Exception e) {System.out.println(" e.printStackTrace() ==== start");e.printStackTrace();System.out.println(" e.printStackTrace() ==== end ");System.out.println();System.out.println(" e.getMessage() ==== start");System.out.println(e.getMessage());System.out.println(" e.getMessage() ==== end");System.out.println();System.out.println(" e.toString() ==== start");System.out.println(e.toString());System.out.println(" e.toString() ==== end");System.out.println();System.out.println(" e.getExceptionToString() ==== start");System.out.println(Exceptions.getExceptionToString(e));System.out.println(" e.getExceptionToString() ==== end");}
}
1.1、输出结果如下:
e.printStackTrace() ==== start
java.lang.ArithmeticException: / by zeroat com.runcode.springboottourist.test.ExpTest2.test(ExpTest2.java:22)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)at org.junit.runners.ParentRunner.run(ParentRunner.java:363)at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)e.printStackTrace() ==== end e.getMessage() ==== start
/ by zeroe.getMessage() ==== ende.toString() ==== start
java.lang.ArithmeticException: / by zeroe.toString() ==== ende.getExceptionToString() ==== start
java.lang.ArithmeticException: / by zeroat com.runcode.springboottourist.test.ExpTest2.test(ExpTest2.java:22)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)at org.junit.runners.ParentRunner.run(ParentRunner.java:363)at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)e.getExceptionToString() ==== end
1.2、结果分析 :
- e.printStackTrace(): 打印完整的异常堆栈信息
- e.getMessage(): 打印 异常的原因
- e.toString(): 打印 异常类型 和 异常的原因
- e.getExceptionToString(): 打印完整的异常堆栈信息
2、web 环境下 --- 模拟异常信息输出
@RequestMapping("/exp")
@ResponseBody
public String exp(String key){int num = 0 ;try {int i = 3/num ;} catch (Exception e) {System.out.println(" e.printStackTrace() ==== start");e.printStackTrace();System.out.println(" e.printStackTrace() ==== end ");System.out.println();System.out.println(" e.getMessage() ==== start");System.out.println(e.getMessage());System.out.println(" e.getMessage() ==== end");System.out.println();System.out.println(" e.toString() ==== start");System.out.println(e.toString());System.out.println(" e.toString() ==== end");System.out.println();System.out.println(" e.getExceptionToString() ==== start");System.out.println(Exceptions.getExceptionToString(e));System.out.println(" e.getExceptionToString() ==== end");}return "success";
}
2.1、输出结果如下:
e.printStackTrace() ==== starte.printStackTrace() ==== end e.getMessage() ==== start
/ by zeroe.getMessage() ==== ende.toString() ==== start
java.lang.ArithmeticException: / by zeroe.toString() ==== ende.getExceptionToString() ==== start
java.lang.ArithmeticException: / by zeroat com.runcode.springboottourist.ExpController.exp(ExpController.java:54)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)at java.lang.Thread.run(Thread.java:748)e.getExceptionToString() ==== end
java.lang.ArithmeticException: / by zeroat com.runcode.springboottourist.ExpController.exp(ExpController.java:54)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)at java.lang.Thread.run(Thread.java:748)
2.2、结果分析:
- e.printStackTrace(): 打印完整的异常堆栈信息 (在e.getExceptionToString 后面) e.getMessage(): 打印 异常的原因
- e.toString(): 打印 异常类型 和 异常的原因
- e.getExceptionToString(): 打印完整的异常堆栈信息
三、总结
1、Exceptions.getExceptionToString(e) 方法,参考这里:java中将异常Exception转化为String字符串输出_HaHa_Sir的博客-CSDN博客
2、e.getMessage() 和 e.toString() 方法: 打印的异常信息太少,没有具体的堆栈信息,不利于问题的定位处理, 不建议使用!
3、e.printStackTrace() 和 Exceptions.getExceptionToString(e) 方法:都可以打印完整的异常堆栈信息; 二者的区别是: e.printStackTrace() 在遇到大量并发访问 且 出现异常时,会发生:内存被占满的情况,导致服务挂掉,不可用 ...
4、日常开发中,会使用 log.error 来打印异常信息,下面比较几种 log.error 打印异常信息的区别:
@RequestMapping("/log")
@ResponseBody
public String log(String key){int num = 0 ;try {int i = 3/num ;} catch (Exception e) {System.out.println(" log.error(\"exp failure \"+ e) ==== start");log.error("exp failure "+ e);System.out.println(" log.error(\"exp failure \"+ e) ==== end");System.out.println();System.out.println(" log.error(\"exp failure {}\"+ e) ==== start");log.error("exp failure {}" + e);System.out.println(" log.error(\"exp failure {}\"+ e) ==== end");System.out.println();System.out.println(" log.error(\"exp failure {}\", e) ==== start");log.error("exp failure {}" , e);System.out.println(" log.error(\"exp failure {}\" ,e) ==== end");System.out.println();System.out.println(" log.error(\"exp failure {}\", getExceptionToString) ==== start");log.error("exp failure {}" , Exceptions.getExceptionToString(e));System.out.println(" log.error(\"exp failure {}\" ,getExceptionToString) ==== end");}return "success";
}
4.1、输出结果:
1、 log.error("exp failure "+ e) ==== start
2022-09-20 16:48:51.783 ERROR 34220 --- [nio-8080-exec-8] c.r.springboottourist.ExpController : exp failure java.lang.ArithmeticException: / by zero
log.error("exp failure "+ e) ==== end
2、 log.error("exp failure {}"+ e) ==== start
2022-09-20 16:48:51.783 ERROR 34220 --- [nio-8080-exec-8] c.r.springboottourist.ExpController : exp failure {}java.lang.ArithmeticException: / by zero
log.error("exp failure {}"+ e) ==== end
3、 log.error("exp failure {}", e) ==== start
2022-09-20 16:48:51.784 ERROR 34220 --- [nio-8080-exec-8] c.r.springboottourist.ExpController : exp failure {}
java.lang.ArithmeticException: / by zero
-- 省略异常堆栈信息
log.error("exp failure {}" ,e) ==== end
4、 log.error("exp failure {}", getExceptionToString) ==== start
2022-09-20 16:48:51.785 ERROR 34220 --- [nio-8080-exec-8] c.r.springboottourist.ExpController : exp failure java.lang.ArithmeticException: / by zero
-- 省略异常堆栈信息
log.error("exp failure {}" ,getExceptionToString) ==== end
4.2、结果分析:
- 1、2 两种情况:都是属于拼接字符串,实际调用的是 e.toString() 方法
- 3 :使用了占位符输出日志,打印了完整的堆栈信息, 但是 占位符 貌似没被识别到。
- 4 :使用了占位符输出日志,打印了完整的堆栈信息, 将异常对象转换为字符串后, 占位符 被识别到。
5、日常开发工作中,该用哪个方法打印异常信息呢:
1.异常对象转换为字符串:
String errMsg = Exceptions.getExceptionToString(e);2. 日志输出:
log.error("exp failure : {}",errMsg);