System.setProperty 对于在另一个 class 中调用静态方法后未修改的记录器

System.setProperty for logger not modified after static method call in another class

我有一个程序,我需要在其中设置记录器格式,但由于有几个入口点(我不控制所有入口点),我想在构造函数中调用 System.setProperty() class 所有入口点汇聚的地方。

主要class

public static void main(String[] args) throws Exception {
    String foo = "bar";
    String baz = "boo";
    static final String FORMATTER_CONFIG = "%1$tb %1$td, %1$tY %1$tr %4$s: %5$s%n";

    SomeClass sc = new SomeClass();
    sc.method1(foo);
    sc.method2(baz);

    try {
        SomeOtherClass soc = SomeOtherClass.newInstance();
    } catch (Exception e) {;
    }
    // Next line will update the property of the logging formatter for this instance
    System.setProperty("java.util.logging.SimpleFormatter.format", FORMATTER_CONFIG);
    MyThirdClass mtc = MyThirdClass.getStaticMethod(foo, baz);

    Logger logger = Logger.getLogger("myProject.main");
    Handler h = new FileHandler("LogHere.txt");
    h.setFormatter(new SimpleFormatter());
    logger.addHandler(h);
    logger.setLevel(Level.INFO);
    logger.info("Info level log");
    logger.fine("Fine level log");
    logger.finer("Finer level log");
    logger.finest("Finest level log");
}

MyThirdClass 的构造函数:

public MyThirdClass() throws SecurityException {
    this.classStaticVar = EntirelyDifferentClass.getVar();
    logger = Logger.getLogger(this.getClass().getName());
    Handler h = null;
    try {
        h = new FileHandler("MTC_LogHere.txt");
    } catch (IOException ex) {
        logger.warning("Failed to initialize custom FileHandler for MTC_LogHere.txt");
    }
    h.setFormatter(new SimpleFormatter());
    logger.addHandler(h);
    logger.setLevel(Level.INFO);
}

我想将对 System.setProperty 的调用作为 MyThirdClass 中构造函数的第一行(在对 EntirelyDifferentClass 的调用之前),但是当我这样做时,日志记录没有格式化根据自定义规则。如果我将它留在原处,即在 main 方法中调用 MyThirdClass 之前的那一行,它会按预期工作。请注意,我还尝试将 System.setProperty 的代码块放入 getStaticMethod() 方法中。

我知道 system.properties 都是静态变量,所以我必须相信在调用 MyThirdClass.getStaticMethod 的方法期间 JVM 中发生的任何事情都会在我可以之前锁定静态属性更改。

  1. 我是否正确理解了 JVM 中发生的事情?
  2. 由于我在实际制作中并没有控制所有的入口点 这个程序的版本,我也不控制编译 设置也不能发出 -Djava 行命令来设置属性 那样(我也验证过会起作用)我需要能够 在 MyThirdClass 中以编程方式执行此操作。我是什么 missing/overlooking,还是我运气不好?

当您调用静态方法时,例如您的情况下的 getStaticMethod(),不会创建 class 的实例,因此不会调用构造函数。

尝试将 System.setProperty() 放在静态方法中而不是构造函数中。

例如:

import java.util.logging.*;

public class Main {
    public static void main(String[] args) {
        SomeClass.staticMethod();

        Logger logger = Logger.getLogger(Main.class.getName());
        logger.setLevel(Level.INFO);
        logger.info("Info level log");
    }
}

public class SomeClass {
    public static void staticMethod() {
        final String FORMATTER_CONFIG = "%1$tb %1$td, %1$tY %1$tr %4$s: %5$s%n";
        System.setProperty("java.util.logging.SimpleFormatter.format", FORMATTER_CONFIG);
    }
}

这个答案最初被 OP Bryan 编辑到上面的问题中,我在这里发布并要求他自己这样做:

For anyone wanting to know the answer, I added a static block at the class level of MyThirdClass:

  protected static Logger logger = null;

  static {
      System.setProperty("java.util.logging.SimpleFormatter.format", FORMATTER_CONFIG);
      logger = Logger.getLogger("myProject.MyThirdClass");
      Handler h = null;
      try {
         h = new FileHandler("LogHere.txt");
      }
      catch (Exception ex) {
          System.out.println("Exception");
      }
      h.setFormatter(new SimpleFormatter());
      logger.addHandler(h);
      logger.setLevel(Constants.LOGGING_LEVEL);
  }