Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to deal with the underlying JDK Logging log module of java

2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of "how to deal with the java underlying JDK Logging log module". The editor shows you the operation process through an actual case. The operation method is simple, fast and practical. I hope this article "how to deal with the java underlying JDK Logging log module" can help you solve the problem.

Start with an example

The use of JDK Logging is simple, as shown in the following code, you can get a logger by using the static method getLogger of the Logger class, and then log input can be made anywhere through the obtained logger. For example, something like logger.info ("Main running.") A call to.

Package com.bes.logging;import java.util.logging.Level;import java.util.logging.Logger;public class LoggerTest {private static Loggerlogger = Logger.getLogger ("com.bes.logging"); public static void main (String argv []) {/ / Log a FINEtracing message logger.info ("Main running."); logger.fine ("doingstuff") Try {Thread.currentThread (). Sleep (1000); / / do some work} catch (Exception ex) {logger.log (Level.WARNING, "trouble sneezing", ex);} logger.fine ("done");}

If you do not make any code changes or JDK configuration changes, run the above example and you will find that the [Main running.] log will only appear on the console. The following questions should appear in your mind.

1, why is there no output of logs other than [Main running.]? How do you make them appear?

2, where does the time, class name, method name, etc. that appear in the log come from?

3, why does the log appear on the console?

4. A large system may have many sub-modules (which can be simply understood as having many package names). How do you control these sub-modules at a separate log level?

5, expansion: is there any connection between apache's popular log4j project and JDK's logging, and how to implement your own LoggerManager?

With these questions, you may be more interested in learning about the logging mechanism of JDK. This chapter analyzes the mechanism of this simple module for you.

Terminology solution

Before further analysis, you need to master the following terms

Logger: for logger, you need to know the next few aspects

1. Logger is used wherever the code needs to enter the log, which is almost the spokesman of a JDK logging module, we often use Logger.getLogger ("com.aaa.bbb"); get a logger, and then use logger as the log output.

2 Logger.getLogger logger is actually just a logical management unit, and most of its operations are just passed on as a relay. For example, the call to Logger.getLogger ("xxx") will depend on the LogManager class, and all handler in logger will be called to input log information when using logger to input log information.

3The recorder logger has a hierarchical relationship, which can be generally understood as the parent-son inheritance relationship between package names. Each logger is usually named after the java package name. The child logger usually inherits the logger level, handler, ResourceBundle name (related to internationalization information) from the parent logger, and so on.

4, there will be a root logger with an empty name throughout the JVM, and all anonymous logger will have root logger as their father

LogManager: the management of all logger within the entire JVM, the generation and acquisition of logger depend on it, including the reading of configuration files. There will be a Hashtable [private Hashtable loggers] in the LogManager to store all the current logger. If you need to obtain the logger, if the logger already exists in the Hashtable, it will be returned directly to the Hashtable. If there is no logger in the hashtable, create a new one and put it in the Hashtable to save it.

Handler: used to control the log output, for example, the ConsoleHanlder included in JDK redirects the output stream to System.err output. Every time you call the method of Logger to output, the publish method of Handler is called, and each logger has multiple handler. We can use handler to input logs to different places (such as file systems or remote Socket connections).

Formatter: the log needs to be formatted before it is actually output: for example, whether to output time or not? Time format? Do you want to enter a thread name? Whether or not to use internationalization information, etc., depends on Formatter.

Log Level: needless to say, this is easy to understand, and that's why logging can help us adapt to the different requirements for log output granularity at different stages from development and debugging to deployment. The JDK Log level from high to low is OFF (231-1)-> SEVERE (1000)-> WARNING (1000)-> INFO (800)-> CONFIG (700)-> FINE (500)-> FINER (400)-> FINEST (300)-> ALL (- 231). Each level corresponds to a number. The comparison of the level when outputting the log depends on the comparison of the number size. However, it should be noted that not only logger has a level, but handler also has a level, that is, if a certain logger level is FINE, customers want to enter FINE-level logs, and if the corresponding handler level of logger is INFO, then FINE-level logs still cannot be exported.

Summarize the corresponding relationship

LogManager has a 1-to-many relationship with logger. There is only one LogManager for the whole JVM runtime, and all logger are in the LogManager.

There is a many-to-many relationship between logger and handler. When logger makes log output, it will call all hanlder to process the log.

There is an one-to-one relationship between handler and formatter. A handler has a formatter to format the log.

It is obvious that there is an one-to-one relationship between logger and level, and between hanlder and level.

Logging configuration:

The default logging configuration file for JDK is $JAVA_HOME/jre/lib/logging.properties. You can use the system property java.util.logging.config.file to overwrite the default profile. The configuration file usually contains the following partial definitions:

1, handlers: separate each Handler with a comma, and these handler will be added to the root logger. That is, even if we do not configure the handler attribute for the other logger, the logger will always find the root logger when the log is output, and then find the handler to input the log.

2, .level is the log level of root logger

3, .xxx is the attribute that configures a specific handler. For example, java.util.logging.ConsoleHandler.formatter configures the corresponding log Formatter for ConsoleHandler.

4, the configuration of logger, all attributes ending in [.level] are considered to be the definition of the level of a certain logger, for example, com.bes.server.level=FINE defines the level of logger named [com.bes.server] as FINE. By the way, the inheritance relationship of logger was mentioned earlier, and if there is a logger of com.bes.server.webcontainer, and no attributes of the logger are defined in the configuration file, then it will inherit from the logger of [com.bes.server]. In addition to the level, you can also define handler and useParentHandlers (default is true) properties for logger, such as com.bes.server.handler=com.bes.test.ServerFileHandler (a class that needs to be an extends java.util.logging.Handler) and com.bes.server.useParentHandlers=false (meaning that when the logger of com.bes.server makes log output, the log is processed only once, with its own handler output, and is not passed to the handler of the parent logger). The following is an example of a JDK configuration file

Handlers= java.util.logging.FileHandler,java.util.logging.ConsoleHandler.level= INFOjava.util.logging.FileHandler.pattern =% h/java%u.logjava.util.logging.FileHandler.limit = 50000java.util.logging.FileHandler.count = 1java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatterjava.util.logging.ConsoleHandler.level = INFOjava.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormattercom.xyz.foo.level = SEVEREsun.rmi.transport.tcp.logLevel = FINELogging acquisition of the operating principle Logger

A, the first step is to call the following method of Logger to get a logger

Public static synchronized Logger getLogger (String name) {LogManager manager = LogManager.getLogManager (); returnmanager.demandLogger (name);}

B, the above call will trigger the class initialization of java.util.logging.LoggerManager. LoggerManager has a static initialization block (this is the ~ _ ~ that will precede the constructor call of LoggerManager):

Static {AccessController.doPrivileged (newPrivilegedAction () {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 (Exceptionex) {System.err.println ("Could not load Logmanager\"+ cname+"\ ") Ex.printStackTrace ();} if (manager = = null) {manager = newLogManager ();} manager.rootLogger= manager.new RootLogger (); manager.addLogger (manager.rootLogger); Logger.global.setLogManager (manager); manager.addLogger (Logger.global); return null;}}) }

You can see from the static initialization block that LoggerManager can be replaced by using the system property java.util.logging.manager to specify a class that inherits from java.util.logging.LoggerManager, such as in the Tomcat startup script to use its own LoggerManager.

Whether it is the JDK default java.util.logging.LoggerManager or a custom LoggerManager, two logger are added to the LoggerManager during initialization, one is the root logger named "", and the logger level is set to the default INFO;, the other is the global logger named global, and the level is still INFO.

After LogManager "class" initialization is completed, the configuration file is read (the default is $JAVA_HOME/jre/lib/logging.properties), and key-value pairs such as property names and values of the configuration file are kept in memory for later use when initializing logger.

The getLogger operation initiated by the Logger class in step Corey A will call the following method of java.util.logging.LoggerManager:

Logger demandLogger (String name) {Logger result = getLogger (name); if (result = = null) {result = newLogger (name, null); addLogger (result); result = getLogger (name);} return result;}

As you can see, LoggerManager first looks from the existing logger list, and if it can't find it, it creates a new looger and adds it to the list. Of course, it is important that the logger needs to be initialized after the new looger is created. For more information on this initialization, please see the java.util.logging.LoggerManager#addLogger () method. The change method sets the logger level and adds handler to the logger according to the configuration file.

So far, logger has obtained it, and you also need to know that you already have important information such as level and handler in your logger. The following will analyze the logic when outputting the log.

Output of the log

First of all, we usually call the method under the Logger class, passing in the log level and log content.

Public void log (Levellevel, String msg) {if (level.intValue () < levelValue | | levelValue = = offValue) {return;} LogRecord lr = new LogRecord (level, msg); doLog (lr);}

This method shows that the Logger class first performs a level check, and if the level check passes, a new LogRecord object will be created. In addition to the log level and log content, the LogRecord will also contain the calling thread information, log time, etc.; then call the doLog (LogRecord lr) method

Private void doLog (LogRecord lr) {lr.setLoggerName (name); String ebname = getEffectiveResourceBundleName (); if (ebname! = null) {lr.setResourceBundleName (ebname); lr.setResourceBundle (findResourceBundle (ebname));} log (lr);}

After the ResourceBundle information (which is related to internationalization) is set in the doLog (LogRecord lr) method, the log (LogRecord record) method is called directly

Public void log (LogRecord record) {if (record.getLevel (). IntValue ()

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report