赞
踩
在软件开发过程中日志记录是必不可少的一部分。作为一个合格的软件开发者(Java),有必要深入了解一下Java的日志体系。本文将详细的介绍我在学习JUL时的一些方法和心得。
一般来说日志分为两种:业务日志和异常日志,使用日志我们希望能达到以下目标:
- 对程序运行情况的记录和监控;
- 在必要时可详细了解程序内部的运行状态;
- 对系统性能的影响尽量小;
个人觉得记录日志最重要的目的在于记录程序运行的信息,以方便分析程序的运行结果和定位问题。
梳理了自己学习JUL的过程,并进行总结,以便在学习其他技术时也能使用这种学习方法。
软件包 java.util.logging 的描述
提供 JavaTM 2 平台核心日志工具的类和接口。Logging API 的中心目标是支持在客户站点进行软件的维护和服务。
使用日志有 4 个主要目标:
1.由最终用户和系统管理员进行问题诊断。这由简单的常见问题日志组成,可在本地解决或跟踪这些问题,如资源不足、安全失败和简单的配置错误。
2.由现场服务工程师进行问题诊断。现场服务工程师使用的日志信息可以相当复杂和冗长,远超过系统管理员的要求。通常,这样的信息需要特定子系统中的额外日志记录。
3.由开发组织进行问题诊断。在现场出现问题时,必须将捕获的日志信息返回到原开发团队以供诊断。此日志信息可能非常详细,并且相当费解。这样的信息可能包括对特定子系统进行内部执行的详细跟踪。
4.由开发人员进行问题诊断。Logging API 还可以用来帮助调试正在开发的应用程序。这可能包括由目标应用程序产生的日志信息,以及由低级别的库产生的日志信息。但是要注意,虽然这样使用非常合理,但是 Logging API 并不用于代替开发环境中已经存在的调试和解析工具。
此包的关键元素包括:
Logger:应用程序进行 logging 调用的主要实体。Logger 对象用来记录特定系统或应用程序组件的日志消息。
LogRecord:用于在 logging 框架和单独的日志处理程序之间传递 logging 请求。
Handler:将 LogRecord 对象导出到各种目的地,包括内存、输出流、控制台、文件和套接字。为此有各种的 Handler 子类。其他 Handler 可能由第三方开发并在核心平台的顶层实现。
Level:定义一组可以用来控制 logging 输出的标准 logging 级别。可以配置程序为某些级别输出 logging,而同时忽略其他输出。
Filter:为所记录的日志提供日志级别控制以外的细粒度控制。Logging API 支持通用的过滤器机制,该机制允许应用程序代码附加任意的过滤器以控制 logging 输出。
Formatter:为格式化 LogRecord 对象提供支持。此包包括的两个格式器 SimpleFormatter 和 XMLFormatter 分别用于格式化纯文本或 XML 中的日志记录。与 Handler 一样,其他 Formatter 可能由第三方开发。
Logging API 提供静态和动态的配置控制。静态控制使现场服务人员可以建立特定的配置,然后重新启动带有新 logging 设置的应用程序。动态控制允许对当前正在运行的系统内的 logging 配置进行更新。API 也允许对不同的系统功能领域启用或禁用 logging。例如,现场服务工程师可能对跟踪所有 AWT 事件感兴趣,但是不会对套接字事件或内存管理感兴趣。
从JDK(java.util.logging)的API中可以看出:
JUL主要由这七个核心类或接口组成,再有就是一些子类或者实现类。API中关于这几个类或接口的类和方法的详细介绍这里不再复述。
现在我们已经对JUL有了一个整体的了解,并且对核心类或接口的功能职责也有了初步了解,接下就该结合代码看看JUL的真面目。
找到rt.jar,打开java.util.logging包查看每个类的源代码,结合JUL流程示意图逐个介绍。
1.Logger类
package java.util.logging; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; import sun.reflect.Reflection; public class Logger { //------------------------------属性------------------------------------------ private String name;//日志名称 private static final int offValue = Level.OFF.intValue(); // We keep weak references from parents to children, but strong // references from children to parents. private volatile Logger parent; // our nearest parent. private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent //内部类LoggerBundle相关部分忽略 private volatile LogManager manager; private static final Handler emptyHandlers[] = new Handler[0]; private final CopyOnWriteArrayList<Handler> handlers = new CopyOnWriteArrayList<>(); private volatile boolean useParentHandlers = true; private volatile Filter filter; private volatile Level levelObject; private volatile int levelValue; // current effective level value private static final Object treeLock = new Object(); private final boolean isSystemLogger; //------------------------------构造器------------------------------------------ //只保留一个简单的私有构造器 private Logger(String name) { // The manager field is not initialized here. this.name = name; this.isSystemLogger = true; levelValue = Level.INFO.intValue();//初始化级别INFO } //------------------------------方法------------------------------------------ //获取Logger的name public String getName() { return name; } // It is called from LoggerContext.addLocalLogger() when the logger // is actually added to a LogManager. //--------------设置和初始化LogManager,包权限的方法------------- void setLogManager(LogManager manager) { this.manager = manager; } private void checkPermission() throws SecurityException { if (manager == null) { // Complete initialization of the global Logger. manager = LogManager.getLogManager(); } manager.checkPermission(); } //-------------------获取Logger的工厂方法---------------------- public static Logger getLogger(String name) { //获取需要的Logger return demandLogger(name, null, Reflection.getCallerClass()); } private static Logger demandLogger(String name, String resourceBundleName, Class<?> caller) { //初始化LogManager LogManager manager = LogManager.getLogManager(); // SecurityManager sm = System.getSecurityManager(); // if (sm != null) { // if (caller.getClassLoader() == null) { // return manager.demandSystemLogger(name, resourceBundleName); // } // } // //通过LogManager获取需要的Logger return manager.demandLogger(name, resourceBundleName, caller); } //--------------------Filter的方法---------------------- public void setFilter(Filter newFilter) throws SecurityException { //校验权限和初始化LogManager checkPermission(); filter = newFilter; } public Filter getFilter() { return filter; } //--------------------记录日志的方法---------------------- // 核心的日志操作方法,handler.publish(record);将LogRecord添加到handlers中 public void log(LogRecord record) { //校验Level if (!isLoggable(record.getLevel())) { return; } //校验Filter Filter theFilter = filter; if (theFilter != null && !theFilter.isLoggable(record)) { return; } Logger logger = this; while (logger != null) { final Handler[] loggerHandlers = isSystemLogger ? logger.accessCheckedHandlers() : logger.getHandlers(); for (Handler handler : loggerHandlers) { handler.publish(record); } final boolean useParentHdls = isSystemLogger ? logger.useParentHandlers : logger.getUseParentHandlers(); if (!useParentHdls) { break; } logger = isSystemLogger ? logger.parent : logger.getParent(); } } private void doLog(LogRecord lr) { lr.setLoggerName(name); //忽略LogBundle log(lr); } public void log(Level level, String msg) { if (!isLoggable(level)) { return; } LogRecord lr = new LogRecord(level, msg); doLog(lr); } public void log(Level level, String msg, Object param1) { if (!isLoggable(level)) { return; } LogRecord lr = new LogRecord(level, msg); Object params[] = { param1 }; lr.setParameters(params); doLog(lr); } public void log(Level level, String msg, Object params[]) { if (!isLoggable(level)) { return; } LogRecord lr = new LogRecord(level, msg); lr.setParameters(params); doLog(lr); } //------------------日志级别相关----------------------- public void setLevel(Level newLevel) throws SecurityException { checkPermission(); synchronized (treeLock) { levelObject = newLevel; updateEffectiveLevel(); } } final boolean isLevelInitialized() { return levelObject != null; } public Level getLe
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。