【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java日志——基本日志+高级日志 的相关知识;


【1】记录日志

1.1)出现的问题和解决方法:

  • 1.1.1)出现的问题:在我们调试的时候, 通过喜欢 插入 System.out.println 语句来辅助我们调试, 当出现新的问题,又要插入 该语句进行调试。
  • 1.1.2)解决方法:记录日志API 就是为了解决这个问题而设计的。

1.2)下面是记录日志 API的优点(Priority):

  • P1)可以很容易地取消全部日志记录, 或者仅仅取消某个级别的日志, 而且打开和关闭这个操作也很容易;
  • P2)可以很简单地禁止日志记录的输出, 因此,将这些日志代码留在程序中的开销很小;
  • P3)日志记录可以被定向到不同的处理器, 用于在控制台中显示, 用于存储在文件中等;
  • P4)日志记录器和处理器都可以对记录进行过滤。 过滤器可以根据过滤实现器制定的标准丢弃那些无用的记录项;
  • P5)日志记录可以采用不同的方式格式化,例如, 纯文本或 xml;
  • P6)应用程序可以使用 多个 日志记录器, 他们使用类似包名的这种具有层次结构的名字, 如, com.a.b.c;
  • P7)在默认情况下, 日志系统的配置由配置文件控制。 如果需要的话, 应用程序可以替换这个配置;

【2】基本日志

2.1)看个荔枝:日志系统管理者一个名为 Logger.global 的默认日志记录器, 可以用System.out 替换他, 并通过调用 info 方法记录日志信息:

Logger.getGlobal().info("File->Open menu item seleted");

2.1.1)在默认情况下,这条记录将会显示如下内容:

May 10, 2013 10:12:25 PM LoggingImageView fileOpen
INFO: FIle->Open menu item selected

java 启动无日志 java运行日志_日志记录


Attention)

  • A1)自动包含了 时间、调用的类名和方法名;
  • A2) 如果在相应的地方调用 Logger.getGlobal().setLevel(Level.OFF);将会取消所有日志;

Warning)在修改bug 7184195 前,还需要调用 Logger.getGlobal().setLevel(Level.INFO)来激活全局日志记录器;


【3】高级日志

3.1)在一个专业的应用程序中, 不要将所有的日志都记录到 一个全局日志记录器中, 而是可以自定义日志记录器;
* 3.1.1)调用 getLogger方法可以创建或 检索记录器

private static final Logger myLogger =  Logger.getLogger("com.mycompany.myapp");

3.2)与包名类似, 日志记录器名也具有层次结构,且层次性更强

  • 3.2.1)对于包来说, 一个包的名字与其父包的名字间没有语义关系, 但是日志记录器的父与子间将共享某些属性;
  • 3.2.2)看个荔枝: 如果对 com.mycompany 日志记录器设置了 日志级别, 它的子记录器也会继承这个级别, 通常有7个日志记录器级别(Level):
  • L1) SEVERE
  • L2) WARNING
  • L3) INFO
  • L4) CONFIG
  • L5) FINE
  • L6) FINER
  • L7) FINEST
  • 3.2.3)默认情况下, 只记录前3个级别, 也可以设置其他级别;
logger.setLevel(Level.FINE);
  • 3.2.4)使用 Level.ALL 开启所有级别的记录, 使用 Level.OFF 关闭所有级别的记录;

3.3)对于所有的基本有下面几种记录方法(Methods):

  • M1) logger.warning(msg);
  • M2) logger.fine(msg);
  • M3)使用log 方法指定级别: logger.log(Lebel.FINE, msg);

Hint)默认的日志配置记录了 INFO 或更高级别的所有记录, 因此,应该使用 CONFIG、FINE, FINER, FINEST 级别来记录那些有助于诊断, 但对于程序员有没有太大意义的调试信息;
Warning)如果将记录设计为INFO 或更低, 则需要修改日志处理器的配置, 默认的日志处理器不会处理低于 INFO 级别的信息;
3.4)默认的日志记录将显示包含日志调用的类名和方法名, 如同堆栈所显示的那样。 但是, 如果虚拟机对执行过程进行了优化, 就得不到准确的调用信息。 此时, 可以调用 logp 方法获得调用类和方法的确切位置, 这个方法的签名为:

void logp(level l , String className, String methodName, String msg)
  • 3.4.1)下面有一些跟踪执行流的方法:
void entering(String className, String methodName)
void entering(String className, String methodName, Object param)
void entering(String className, String methodName, Object[] params)
void entering(String className, String methodName)
void entering(String className, String methodName, Object result)
  • 3.4.2)看个荔枝:
int read(Strinf file, String pattern)
{
    logger.entering("com.mycompany.mylib.Reader", "read", new Object[] {file, pattern});
    ......
    logger.exiting("com.mycompany.mylib.Reader", "read", count);
    return count;
}
  • 这些调用将生成FINER 级别和以 字符串“ENTRY” 和 “RETURN”开始的日志记录;

3.5)记录日志的常见用途是记录那些不可预料的异常。 可以使用下面两个方法提供日志记录中包含的异常描述内容(Methods):

  • 日志记录 API 如下:
void throwing(String className, String methodName, Throwable t)
void log(Level l , String msg, Throwable t)
  • M1)典型用法是:
if(...)
{
    IOException exception = new IOException("");
    logger.throwing("com.mycompany.mylib.Reader", "read", exception);
    throw exception;
}
  • M2)还有一种:
try
{
    ...
}
catch(Exception e)
{
    Logger.getLogger("com.mycompany.myapp").log(Level.WARNING, "Reading image", e);
}
  • 调用throwing 可以记录一条 FINER 级别的记录和一条以 THROW 开始的信息;