JDK日志框架源码分析(一)
来源:互联网 发布:分布式通信 java 编辑:程序博客网 时间:2024/05/29 02:53
分析源码先从它是如何被使用或调用开始,如在上篇文章中说的,代码中使用JDK自带的日志是这样开始的:
Logger logger = Logger.getLogger("W");
那么我们看看getLogger方法的内部:
public static Logger getLogger(String name) { LogManager manager = LogManager.getLogManager(); return manager.demandLogger(name); }
原来最终是通过LogManager的一个实例获取的,且通过静态方法getLoggrManager获取的这个实例:
public static LogManager getLogManager() { if (manager != null) { manager.readPrimordialConfiguration(); } return manager; }
这个方法返回的是成员变量manager,那么它在哪里初始化呢?定义处并没有:
// The global LogManager object private static LogManager manager;
那看来只能在别的地方了。由于并没有创建LogManager的对象,所以不会在构造方法中;由于静态方法的调用会引起类的加载,所以类代码中应该存在一个static块用来初始化manager,一看果然如此:
static { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { String cname = null; try { cname = System.getProperty("java.util.logging.manager"); if (cname != null) { try { Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); manager = (LogManager) clz.newInstance(); } catch (ClassNotFoundException ex) { Class clz = Thread.currentThread().getContextClassLoader().loadClass(cname); manager = (LogManager) clz.newInstance(); } } } catch (Exception ex) { System.err.println("Could not load Logmanager \"" + cname + "\""); ex.printStackTrace(); } if (manager == null) { manager = new LogManager(); } // Create and retain Logger for the root of the namespace. manager.rootLogger = manager.new RootLogger(); manager.addLogger(manager.rootLogger); // Adding the global Logger. Doing so in the Logger.<clinit> // would deadlock with the LogManager.<clinit>. Logger.global.setLogManager(manager); manager.addLogger(Logger.global); // We don't call readConfiguration() here, as we may be running // very early in the JVM startup sequence. Instead readConfiguration // will be called lazily in getLogManager(). return null; } }); }
第一步是加载系统属性java.util.logging.manager指定的类,该属性在启动java程序时指定,比如使用命令行就在java命令后面用这种形式:
-java.util.logging.manager=xx
从代码可以看出,只有在该系统属性指定的类没有加载成功时才会使用JDK本身的LogManager创建实例。这说明,JDK的日志框架允许使用其他的类作为LogManager,这显然考虑到了以后的可扩展性,比如Tomcat就没有使用JDK的LogManager而是使用了自己定义的;当然就算是自己定义的,也必须是LogManager的子类。
有了LogManager的实例之后,就开始为它的成员变量rootLogger赋值,其实就是新建了一个内部类RootLogger的对象。rootLogger的类型是Logger,而RootLogger是Logger的子类:
private class RootLogger extends Logger { private RootLogger() { super("", null); setLevel(defaultLevel); } public void log(LogRecord record) { // Make sure that the global handlers have been instantiated. initializeGlobalHandlers(); super.log(record); } public void addHandler(Handler h) { initializeGlobalHandlers(); super.addHandler(h); } public void removeHandler(Handler h) { initializeGlobalHandlers(); super.removeHandler(h); } public Handler[] getHandlers() { initializeGlobalHandlers(); return super.getHandlers(); } }
在RootLogger的构造方法中可以看到,它调用了父类Logger的构造方法,也就是创建了一个名称为空串“”的Logger,
接着调用addLogger方法把这个名为“”的Logger添加进namedLoggers变量,该变量是一个HashTable:
private Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
下一篇分析addLogger方法。
阅读全文
0 0
- JDK日志框架源码分析(一)
- JDK日志框架源码分析(二)
- JDK源码分析之ArrayList(一)
- RankLib源码分析(一):主框架
- skynet框架 源码分析 一
- min3d框架源码分析(一)
- OKHttp框架源码分析(一)
- MINA框架源码分析(一)
- skynet框架 源码分析 一
- Android Logger 日志框架源码分析
- JDK源码分析之String(一)
- 思科VPP源码分析(路由框架分析一)
- 【JDK集合框架源码分析】-集合框架概述
- jdk源码解析(一)
- JDK日志框架
- JDK日志框架解读
- 网络服务器开发框架spserver源码分析 (一)
- 集合框架源码分析篇一(接口篇)
- shell脚本的8种字符串截取方法
- 接口
- Hot Bath
- Go 基础语言学习笔记
- Activity转场动画效果
- JDK日志框架源码分析(一)
- springmvc属性编辑器和自定义参数解析器
- C语言——define的用法归纳
- Zookeeper集群问题介绍
- POJ-1094 Sorting it All Out
- 最小生成树之prim模板题
- 优雅设计封装基于Okhttp3的网络框架(完):原生HttpUrlConnction请求、多线程分发 及 数据转换
- Java在linux上只能在程序的当前目录下创建文件/文件夹导致的问题
- ORA-01653: unable to extend table SYS.AUD$ by 8192 in tablespace SYSTEM系统表空间满