java log exception

关于异常,在排查问题的时候,日志对于我们显的格外重要,前几天发布的时候就遇到一个悲剧的现象,发布beta测试的时候,发现有个NullPointException,但是日志中只有日志的类全名称,但是没有栈信息以及代码行号,无法定位哪一行跑出来的,于是只能重新改代码,十分之蛋疼。于是把日志相关的东西扫一下雷。

---------------------------------------------------------------------------------------------------------------------

 

日志系统

Log4j —— 较早出现的比较成功的日志系统是Log4jLog4j开创的日志系统模型(Logger/Appender/Level)行之有效,并一直延用至今。

JULjava.util.logging.* —— JDK1.4是第一个自带日志系统的JDK,简称(JUL)。JUL并没有明显的优势来战胜Log4j,反而造成了标准的混乱 —— 采用不同日志系统的应用程序无法和谐共存。

Logback —— 是较新的日志系统。它是Log4j的作者吸取多年的经验教训以后重新做出的一套系统。它的使用更方便,功能更强,而且性能也更高。Logback不能单独使用,必须配合日志框架SLF4J来使用。

-----------------------------------------------------------------------------------------------------------------------

 

引用一篇文章中关于java log的描述。

为了克服多种日志系统并存所带来的混乱,就出现了“日志框架”。日志框架本身不提供记录日志的功能,它只提供了日志调用的接口。基本可以理解,log4j作为log信息的配置,就是日志打在哪里,怎么打等,然后有开源jar包提供了访问日志文件的接口,用来和具体的日志系统解耦,例如commmon-loggingslf4j,提供了LogFactory来获取具体的log对象,获取了log对象后,就可以打日志了。下面是两个常用的日志框架

 

(1)commons-loggingapache提供的日志门面接口,主要是为了避免程序和具体的log耦合。首先需要引入commons-logging.jar(通过maven或者其他方法皆可),然后这样使用就可以了

<!--[if !supportLists]-->1.  <!--[endif]-->Log logger = LogFactory.getLog(TestCommonsLogging.class);

<!--[if !supportLists]-->2.  <!--[endif]-->logger.debug(“test debug”);

 

(2)slf4jcommons-logging功能类似,首先要引入slf4j-api-1.6.4jar,然后比如要支持log4j,就引入slf4j-log4j12-1.6.4jar

Logger logger = LoggerFactory.getLogger(Slf4jTest.class);

logger.debug(“test debug”);

<!--EndFragment-->

-----------------------------------------------------------------------------------------------------------------------

Log4j的几个概念:

1layout:一行日志的格式,正则形式

org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout
(可以灵活地指定布局模式),

%p: 输出日志信息优先级,即DEBUGINFOWARNERRORFATAL,
 %d:
输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS}

 %r: 输出自应用启动到输出该log信息耗费的毫秒数
 %c:
输出日志信息所属的类目,通常就是所在类的全名
 %t:
输出产生该日志事件的线程名
 %l:
输出日志事件的发生位置,

 %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
 %%:
输出一个"%"字符
 %F:
输出日志消息产生时所在的文件名称
 %L:
输出代码中的行号
 %m:
输出代码中指定的消息,产生的日志具体信息
 %n:
输出一个回车换行符,

org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout
(包含日志产生的时间、线程、类别等等信息)

如果需要线程信息,可以加上%t来获取这个信息

2appender:输出日志的位置信息

org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender
(文件),
org.apache.log4j.DailyRollingFileAppender
(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender
(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender
(将日志信息以流格式发送到任意指定的地方)

3level:日志输出等级,共五级,DEBUG/INFO/WARN/ERROR/FATAL

 

-----------------------------------------------------------------------------------------------------------------------

 

 

日志中没有异常栈信息:

JDK5之后JVM有个优化,就是如果一个异常抛出一段时间后,为了性能考虑,后续就不会再抛出stackTrace信息,当然这个功能也可以通过JVM的启动参数来去掉:-XX:-OmitStackTraceInFastThrow.

 

-----------------------------------------------------------------------------------------------------------------------

 

关于Throwable

1getCause()

获取这个抛出的原因;

2getMessage()

获取这个抛出的描述信息,例如throw new Exception("我是抛出来的异常")

这时候次方法会返回括号里面的文本信息

3getStackTrace()

获取抛出的栈信息,printStackTrace()能够打印栈信息。

logger.error("i am zhongyong",e);  输出文本信息以及异常栈信息

logger.error(e);  只是返回异常的名称信息,栈信息没有

 

-----------------------------------------------------------------------------------------------------------------------

 

异常转型在上面已经提到过了,实际上就是捕获到异常后,将异常以新的类型的异常再抛出,这样做一般为了异常的信息更直观!比如:

public void run() throws MyException{

 ...

 try{

  ...

 }catch(IOException e){

  ...

  throw new MyException();

 }finally{

  ...

 }

}

throw new MyException()时候,建议MyExceptione),否则就会出现异常被吃掉的情况。


-----------------------------------------------------------------------------------------------------------------------

 

 

 

对于运行时异常,我们不要用try...catch来捕获处理,而是在程序开发调试阶段,尽量去避免这种异常,一旦发现该异常,正确的做法就会改进程序设计的代码和实现方式,修改程序中的错误,从而避免这种异常。捕获并处理运行时异常是好的解决办法,因为可以通过改进代码实现来避免该种异常的发生。

    对于受检查异常,没说的,老老实实去按照异常处理的方法去处理,要么用try...catch捕获并解决,要么用throws抛出!

对于Error(运行时错误),不需要在程序中做任何处理,出现问题后,应该在程序在外的地方找问题,然后解决。

 

1、避免过大的try块,不要把不会出现异常的代码放到try块里面,尽量保持一个try块对应一个或多个异常。

2、细化异常的类型,不要不管什么类型的异常都写成Excetpion

3catch块尽量保持一个块捕获一类异常,不要忽略捕获的异常,捕获到后要么处理,要么转译,要么重新抛出新类型的异常。

4、不要把自己能处理的异常抛给别人。

5、不要用try...catch参与控制程序流程,异常控制的根本目的是处理程序的非正常情况。

 

 

 

-----------------------------------------------------------------------------------------------------------------------

 

 

 

 

猜你喜欢

转载自iamzhongyong.iteye.com/blog/1600523