JDK内置日志系统
1、Java应用中的日志功能
=================
一般的Java应用程序中都有记录日志的需求,目前主流的记录日志的方法是在应用程序中引入log4j,用log4j来生成日志。其实,JDK带有自己的日志系统,使用起来也很方便。
2、Java内置日志的使用方法
=================
JDK内置的日志系统相关的类都包含在java.util.logging这个包中。下面通过例子,由简到繁解释JDK内置日志系统的使用方法。
为了让应用程序有记录日志的能力,必须先在应用程序中获得一个日志记录器(logger),应用程序想记录的所有日志都发给这个日志记录器,日志记录器会帮助应用程序记录日志。
2.1 直接使用日志系统中的全局日志记录器来记录日志
----------------------------------------------------
下面的例子在Test应用中为了记录日志,获取了日志系统中的全局日志记录器,用这个全局日志记录器简单地记录了几个日志。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import java.util.logging.Logger; public class Test { public static void main(String[] args) { Logger logger = Logger.getGlobal(); //获得日志系统中内置的全局日志记录器 //用获得的全局日志记录器logger记录七条日志记录 logger.severe( "level.severe" ); logger.warning( "level.warning" ); logger.info( "level.info" ); logger.config( "level.config" ); logger.fine( "level.fine" ); logger.finer( "level.finer" ); logger.finest( "level.finest" ); } } |
用javac Test.java命令编译Test应用后,用java Test命令运行Test应用,可以看到Test应用中用全局日志记录器输出的日志,如下:
在下面输出的日志中,每两行是一条日志记录(LogRecord),每条日志记录的第一行是此条日志记录输出的日期和时间,以及输出时所在的类和方法,下面一行是这条日志记录的日志级别(LogLevel)和具体的日志信息(log)。
由于上面的Test应用中输出了七条日志记录,所以运行Test应用后就输出了14行的日志信息,每两行是一条日志记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | zzl @ZZL -PC /e/code/javacode/CoreJava $ javac Test.java zzl @ZZL -PC /e/code/javacode/CoreJava $ java Test 二月 24 , 2017 6 : 29 : 14 下午 Test main 严重: level.severe 二月 24 , 2017 6 : 29 : 14 下午 Test main 警告: level.warning 二月 24 , 2017 6 : 29 : 14 下午 Test main 信息: level.info 二月 24 , 2017 6 : 29 : 14 下午 Test main 配置: level.config 二月 24 , 2017 6 : 29 : 14 下午 Test main 详细: level.fine 二月 24 , 2017 6 : 29 : 14 下午 Test main 较详细: level.finer 二月 24 , 2017 6 : 29 : 14 下午 Test main 非常详细: level.finest |
2.2 使用应用专有的日志记录器来记录日志
-----------------------------------------
除了可以使用日志系统中的全局日志记录器之外,在实际的应用中,我们应该为每一个应用程序单独设置一个本应用程序自己的日志记录器。
可以使用如下语句为myapp应用创建一个名字为com.mycompany.myapp的日志记录器:
Logger myLogger = Logger.getLogger("com.mycompany.myapp");
从这里可以看出,日志记录器的名字和包名很类似,也是有层次结构的。但是它与包名的不同之处在于,对包来说,一个包和包含它的父包之间没有语义关系,但是日志记录器会共享一些属性。比如,名字为com.mycompany的日志记录器是名字为com.company.myapp的日志记录器的父亲,那么如果在日志记录器com.mycompany中设置了日志级别(LogLevel),日志记录器com.mycompany.myapp会继承这个日志级别的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.mycompany; import java.util.logging.Logger; import java.util.logging.Level; public class MyApp { public static void main(String[] args) { //获取名字为com.mycompany.myapp的日志记录器 Logger logger = Logger.getLogger( "com.mycompany.myapp" ); //用获得的日志记录器记录七条日志记录 logger.severe( "level.severe" ); logger.warning( "level.warning" ); logger.info( "level.info" ); logger.config( "level.config" ); logger.fine( "level.fine" ); logger.finer( "level.finer" ); logger.finest( "level.finest" ); } } |
编译、运行以上的MyApp应用,会看到它输出了七条日志记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | zzl @ZZL -PC /e/code/javacode/CoreJava $ javac -d . com/mycompany/MyApp.java zzl @ZZL -PC /e/code/javacode/CoreJava $ java com.mycompany.MyApp 二月 24 , 2017 8 : 04 : 36 下午 com.mycompany.MyApp main 严重: level.severe 二月 24 , 2017 8 : 04 : 36 下午 com.mycompany.MyApp main 警告: level.warning 二月 24 , 2017 8 : 04 : 36 下午 com.mycompany.MyApp main 信息: level.info 二月 24 , 2017 8 : 04 : 36 下午 com.mycompany.MyApp main 配置: level.config 二月 24 , 2017 8 : 04 : 36 下午 com.mycompany.MyApp main 详细: level.fine 二月 24 , 2017 8 : 04 : 36 下午 com.mycompany.MyApp main 较详细: level.finer 二月 24 , 2017 8 : 04 : 36 下午 com.mycompany.MyApp main 非常详细: level.finest |
以上的两个例子介绍了日志记录器的基本用法。
2.3 日志级别(LogLevel)
--------------------------
日志级别代表应用程序想要告诉外界的信息的不同的严重程序,比如特别关键的,不是那么要紧的等。JDK自带的日志系统中的每一个日志记录器都可以有7个日志级别(LogLevel),从高级到低级,它们分别是:SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST。在创建好一个日志记录器后,默认设置的日志级别是INFO,这表示这个日志记录器可以输出INFO及其以上级别的日志,也就是可以输出SEVER、WARNING、INFO这三个级别的日志记录,但是不能输出CONFIG、FINE、FINER、FINEST这四个级别的日志记录,即使在程序调用了相应的输出语句,也不会输出对应级别的日志。
具体见下面的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.mycompany; import java.util.logging.Logger; import java.util.logging.Level; public class MyApp { public static void main(String[] args) { //获取名字为com.mycompany.myapp的日志记录器 Logger logger = Logger.getLogger( "com.mycompany.myapp" ); //用获得的日志记录器记录七条日志记录 //每一个Logger的默认级别是INFO,所以下面的前三条可以输出 //后四条无法输出 logger.severe( "level.severe" ); logger.warning( "level.warning" ); logger.info( "level.info" ); logger.config( "level.config" ); logger.fine( "level.fine" ); logger.finer( "level.finer" ); logger.finest( "level.finest" ); } } |
编译、运行之后,可以看到如下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | zzl @ZZL -PC /e/code/javacode/CoreJava $ javac -d . com/mycompany/MyApp.java zzl @ZZL -PC /e/code/javacode/CoreJava $ java com.mycompany.MyApp 二月 24 , 2017 8 : 18 : 50 下午 com.mycompany.MyApp main 严重: level.severe 二月 24 , 2017 8 : 18 : 50 下午 com.mycompany.MyApp main 警告: level.warning 二月 24 , 2017 8 : 18 : 50 下午 com.mycompany.MyApp main 信息: level.info zzl @ZZL -PC /e/code/javacode/CoreJava $ |
可以看到在INFO级别之下的日志记录都没有输出,只输出了前三个级别的日志记录。
当然可以在日志系统的配置文件中为日志记录器设置日志级别,对于com.mycompany.myapp这个日志记录器,可以在jre/lib/logging.properties中这样设置日志级别,在配置文件的最后,加上如下一句即可:
com.mycompany.myapp.level = FINE
此外,除了日志记录器有日志级别外,处理器也有自己的日志级别,而且处理器的日志级别比日志记录器的日志级别优先级更高,具体见下面一节“日志处理器”。
2.4 日志处理器(Handler)
---------------------------
日志处理器是日志记录实际被发送到的目的地,可以是控制台(console)、文件或者网络服务器。常用的三个系统自带日志处理器,分别是:代表控制台的ConsoleHandler、代表文件的FileHandler、代表网络服务器的SocketHandler。
在创建了一个日志记录器之后,如果没有显式地为其指定处理器,默认情况下,它会将日志记录发送到ConsoleHandler,并由ConsoleHandler输出到System.err中。需要注意的日志记录器除了会把日志记录发送到自己的处理器去,还会把日志记录发送到它的父日志记录器的处理器中去。
日志处理器和日志记录器一样,也有自己的日志级别。默认的ConsoleHandler的日志级别是
java.util.logging.ConsoleHandler.level = INFO
在自己的程序中,可以为自定义的日志记录器指定自己的日志处理器。参见下面的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package com.mycompany; import java.util.logging.Logger; import java.util.logging.Level; import java.util.logging.Handler; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.io.*; public class MyApp { public static void main(String[] args) { //获取名字为com.mycompany.myapp的日志记录器 Logger logger = Logger.getLogger( "com.mycompany.myapp" ); logger.setLevel(Level.ALL); //设置日志管理器的日记级别 logger.setUseParentHandlers( false ); //为com.mycompany.myapp这个日志记录器设置一个ConsoleHandler处理器 Handler handler = new ConsoleHandler(); handler.setLevel(Level.ALL); //设置处理器的日志级别 logger.addHandler(handler); //再为com.mycompany.myapp这个日志记录器设置一个FileHandler处理器 FileHandler handler2 = null ; try { handler2= new FileHandler(); logger.addHandler(handler2); } catch (IOException e) { e.printStackTrace(); } logger.severe( "level.severe" ); logger.warning( "level.warning" ); logger.info( "level.info" ); logger.config( "level.config" ); logger.fine( "level.fine" ); logger.finer( "level.finer" ); logger.finest( "level.finest" ); } } |
上面的程序在编译、运行之后,它会把日志同时送到Console和File中。对于FileHandler,默认情况下,它会把日志记录存到一个名为javan.log(n是一个数字,当多次运行同一个应用程序时,每次n会不一样,这样每次运行的日志就会记录在不同的文件中)的xml文件中,该文件默认情况下位于user.home属性所指的目中,本例子中生成的log文件是c:\users\user1\java0.log。
这些就是日志处理器的基本知识,当然关于日志处理器还有更多可以了解的细节,请参考java.util.logging包中具体API的说明文档。
3、日志系统的配置文件
===============
日志系统的各种属性,比如日志级别等,可以通过日志系统的配置文件来修改。默认情况下,日志系统的配置文件是JAVA_HOME/jre/lib/logging.properties。如果想要为应用程序设置一个独有的配置文件,可以在启用应用程序的时候用java.util.logging.config.file属性来设置,比如,像下面这样:
java -Djava.util.logging.config.file=configFile MyApp
当然,如果想要修改日志系统的默认配置,可以直接编辑jre/lib/logging.properties文件。
编写自己的日志配置文件,可以参考jre/lib/logging.properties文件进行,这里不说了。
4、其他问题
=======
JDK自带的日志系统还有很多细节,这里介绍是一个基本知识,懂了这些就可以用起来,如果想更深入地了解,可以参考java.util.logging包的文档。另外值得注意的地方就是要在学习的过程中,搞清楚基本概念的含义。一定要分清楚,日志记录器、日志记录、日志处理器、日志级别、日志系统的默认配置文件等。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通