JUL 配置 class 应该如何(以及为什么)初始化?

How (and why) should a JUL configuration class be initialized?

我有一个命令行工具 (frontend.java) 使用 args4j 选项 class (Options.java) 和 JUL 配置 class (LogConfig.java) .因为在我的实际应用程序中,我需要查看和使用选定的选项来配置日志记录,所以我在 frontend 中有一个静态的 getter,returns 已选择的各种 args4j 选项用户。

frontend.java:
import java.util.logging.Logger;

public class frontend{
    private static Logger log = Logger.getLogger(frontend.class.getName());
    private static Options opts = new Options();

    public frontend(){
        System.out.println("Made a new front end");
    }
    public static Options getOptions(){
        if(opts == null)
            System.out.println("Opts was null");
        else
            System.out.println("Opts is not null");
        return opts;

    }
    public static void main(String[] args) {
        frontend fe = new frontend();
    }
}

显然,下一个文件并不是真正的空白,但我不确定我是否需要此处的任何内容来说明我的问题所在。

Options.java:
public class Options{
}

最后,配置class:

LogConfig.java:
import java.util.logging.LogManager;
import java.util.logging.Logger;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class LogConfig {
    public LogConfig() {
        Options opts = frontend.getOptions();
        try {
            LogManager.getLogManager().readConfiguration(new FileInputStream("logging.properties"));
        }catch (SecurityException e) {
            System.err.println("Problem accessing log config file: "
                               + e.getMessage());
        } catch (IOException e) {
            System.err.println("Problem loading log config file: "
                               + e.getMessage());
        }
    }
}

我的问题是 LogConfig class 似乎在静态初始化设置之前获取了 opts 变量:

Output:
c:\>java -cp . frontend
Made a new front end
Opts is not null

c:\>java -Djava.util.logging.config.class=LogConfig -cp . frontend
Opts was null
Made a new front end
Opts is not null

c:\>

当您的主程序 class 在您知道您的配置 class 需要完成什么之前必须有点活跃时,使用 JUL 日志配置 class 的最佳方法是什么?

创建 Logger 会触发 LogManager 启动。延迟创建您的记录器,直到您需要使用它。

public class frontend {

    private static volatile Logger log;
    private static Options opts = new Options();

    public frontend() {
        System.out.println("Made a new front end");
    }

    public static Options getOptions() {
        if (opts == null) {
            System.out.println("Opts was null");
        } else {
            System.out.println("Opts is not null");
        }
        return opts;

    }

    public static void main(String[] args) {
        frontend fe = new frontend();
        log = Logger.getLogger(frontend.class.getName());
    }
}

否则,您可以在 LogManager 启动完成后自己重新创建配置 class。然后让您的 LogConfig 在 getOptions returns null.

时执行空操作
public class frontend {

    private static final Logger log = Logger.getLogger(frontend.class.getName());
    private static Options opts = new Options();

    public frontend() {
        System.out.println("Made a new front end");
    }

    public static Options getOptions() {
        if (opts == null) {
            System.out.println("Opts was null");
        } else {
            System.out.println("Opts is not null");
        }
        return opts;

    }

    public static void main(String[] args) {
        frontend fe = new frontend();
        init();
    }

    private static void init() {
        String n = System.getProperty("java.util.logging.config.class");
        if (n != null) {
            try { //LogManager uses the system class loader.
                Class<?> k = Class.forName(n, false,
                        ClassLoader.getSystemClassLoader());
                k.newInstance();
            } catch (ReflectiveOperationException | LinkageError ignore) {
                ignore.printStackTrace();
            }
        }
    }
}