为什么我的 java 日志记录会像文件一样转到控制台

Why does my java logging go to console as well as file

我使用 -Djava.util.logging.config.class=com.jthink.songkong.logging.StandardLogging

将我的应用程序配置为使用日志 class 而不是 jre conf 文件夹中的 logging.properties 文件

它起作用了,除了我注意到那些原本打算进入我的日志文件的信息也将进入控制台 window,在将 --win-console 与 jpackage 一起使用时会注意到这一点在 Windows 上,但我认为在我使用 JPackage

之前它已经发生了

这是我的日志class:

public final class StandardLogging
{

public static int LOG_SIZE_IN_BYTES = 10000000;

//Default parent logger
public static  Logger  defaultLogger                = Logger.getLogger("");

//jaudiotagger logger
public static  Logger  ioLogger                     = Logger.getLogger("org.jaudiotagger");

//SongKong logger
public static  Logger  debugLogger                  = Logger.getLogger("com.jthink");

//SongKong usaer Message Logger
public static  Logger  userInfoLogger               = Logger.getLogger("com.jthink.songkong.ui.MainWindow");

//General c3p0
public static  Logger  c3p0Logger                   = Logger.getLogger("com.mchange.v2.c3p0");

//For capturing Preapred stament Cache hits
//public static  Logger  c3p0ConnectionLogger         = Logger.getLogger("com.mchange.v2.c3p0.stmt");

//For capturing stack traces when connection lasted too long
public static  Logger  c3p0PooledConnectionLogger   = Logger.getLogger("com.mchange.v2.resourcepool.BasicResourcePool");

//HIbernate SQL
public static  Logger  hibernateLogger              = Logger.getLogger("org.hibernate.SQL");



//TODO not sure this even used, I think CmdLogger just does System.out
private static Logger cmdlineLogger = Logger.getLogger("cmdline");

protected void configureLoggerLevels()
{
    //Default Log Level, used by any 3rd party libs we are using if not configured further
    defaultLogger.setLevel(Level.WARNING);

    //For Debug (songKong and jaudiotagger)
    ioLogger.setLevel(Level.WARNING);
    ioLogger.setUseParentHandlers(false);

    try
    {
        //If GeneralPreferences exist and we can access set from user value
        ioLogger.setLevel(Level.parse(String.valueOf(GeneralPreferences.getInstance().getIoDebugLevel())));
    }
    catch(Exception ex)
    {

    }

    debugLogger.setLevel(Level.WARNING);
    debugLogger.setUseParentHandlers(false);
    try
    {
        //If GeneralPreferences exist and we cBuildBuiklan access set from user value
        debugLogger.setLevel(Level.parse(String.valueOf(GeneralPreferences.getInstance().getDebugLevel())));
    }
    catch(Exception ex)
    {

    }

    //C3p0 Logger
    c3p0Logger.setLevel(Level.INFO);
    c3p0Logger.setUseParentHandlers(false);

    //Set to FINEST to see SQL
    hibernateLogger.setLevel(Level.WARNING);
    hibernateLogger.setUseParentHandlers(false);

    //For Capturing CheckIn/Outs nad Prepared Statement Cache Hits
    //c3p0ConnectionLogger.setLevel(Level.FINEST);
    //c3p0ConnectionLogger.setUseParentHandlers(false);

    //For capturing stacktrace from timed out connections
    c3p0PooledConnectionLogger.setLevel(Level.INFO);
    c3p0PooledConnectionLogger.setUseParentHandlers(false);

    //For user message log
    userInfoLogger.setUseParentHandlers(false);
    userInfoLogger.setLevel(Level.FINEST);

    userInfoLogger.setUseParentHandlers(false);
    userInfoLogger.setLevel(Level.FINEST);

}

protected void configureHandlers() throws Exception
{
    //Set Filehandler used for writing to debug log
    String logFileName = Platform.getPlatformLogFolderInLogfileFormat() + "songkong_debug%u-%g.log";
    FileHandler fe = new FileHandler(logFileName, LOG_SIZE_IN_BYTES, 10, true);
    fe.setEncoding(StandardCharsets.UTF_8.name());
    fe.setFormatter(new LogFormatter());
    fe.setLevel(Level.FINEST);

    //Set Filehandler used for writing to user log
    String userLogFileName = Platform.getPlatformLogFolderInLogfileFormat() + "songkong_user%u-%g.log";
    FileHandler userFe = new FileHandler(userLogFileName, LOG_SIZE_IN_BYTES, 10, true);
    userFe.setFormatter(new com.jthink.songkong.logging.UserLogFormatter());
    userFe.setLevel(Level.FINEST);

    //Write this output to debug log file
    //defaultLogger.addHandler(fe);
    c3p0Logger.addHandler(fe);
    c3p0PooledConnectionLogger.addHandler(fe);
    //c3p0ConnectionLogger.addHandler(fe);
    ioLogger.addHandler(fe);
    debugLogger.addHandler(fe);
    hibernateLogger.addHandler(fe);

    //Write this output to user log file
    userInfoLogger.addHandler(userFe);

    //For cmd line output, is this still used
    cmdlineLogger.setUseParentHandlers(false);
    ConsoleHandler cmdLineHandler = new java.util.logging.ConsoleHandler();
    cmdLineHandler.setLevel(Level.FINEST);
    cmdLineHandler.setFormatter(new CmdLineFormatter());
    cmdlineLogger.addHandler(cmdLineHandler);

    System.out.println("debuglogfile is:" + logFileName);
    System.out.println("userlogfile is:"  + userLogFileName);

}

public StandardLogging()
{
    try
    {
        configureLoggerLevels();
        configureHandlers();
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
}
}

这是我希望转到我的 songkong-debug0-0.log 文件的代码示例,但它也被输出到控制台 window:

MainWindow.logger.warning("User Dir:"+ System.getProperty("user.dir"));
MainWindow.logger.warning("Java Dir:"+ System.getProperty("java.home"));

为什么会这样?

在配置结束时将代码添加到 com.jthink.songkong.logging.StandardLogging 。这将帮助您解决正在发生的问题。由于您使用的是配置 class,您甚至可以创建自己的系统 属性 以在将来需要时切换打印记录器树。

如果您的控制台输出看起来像您创建的 CmdLineFormatter 的格式,那么代码要么使用该记录器,要么使用打印到父处理程序的子记录器。假设您控制 CmdLineFormatter 的格式,您可以在输出中包含记录器名称以找到有问题的记录器。

如果输出看起来像 SimpleFormatter 那么更有可能是附加到根记录器的控制台处理程序。只需从配置 class.

的根记录器中删除该处理程序

更完整的解决方案是在 StandardLogging class 构造函数的开头调用 LogManager.reset。这将清除 JRE 在调用您的更改之前设置的配置。除了设置 java.util.logging.config.class.

之外,另一种方法是从命令行设置 java.util.logging.config.file to point to a null device