Find log file name at run time with Java 9 JDK Log

2019-08-23 04:23发布

I have the same question as Find actual opened logfile with JDK Logging, except that I want to use an API that's supported by Java 9.

In Java 8, I currently use nearly the same reflection hack as described in the answer to that question except that I look at the actual log file name instead of parsing the lockFileName.

Here's my code:

private static String logFileName = null;

public static String getLogFileName() {
    // determined on demand and cached so we only need to do all of this the first time.
    if (logFileName == null) {
        for (Handler handler : Logger.getLogger("").getHandlers()) {
            if (handler.getClass().isAssignableFrom(FileHandler.class)) {
                FileHandler fileHandler = (FileHandler) handler;
                try {
                    // FileHandler.files has private access, 
                    // so I'm going to resort to reflection to get the file name.
                    Field privateFilesField = fileHandler.getClass().getDeclaredField("files");
                    privateFilesField.setAccessible(true); // allow access to this private field
                    File[] files = (File[]) privateFilesField.get(fileHandler);
                    logFileName = files[0].getCanonicalPath();
                    break;
                } catch (NullPointerException | NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException | IOException ex) {
                    logger.log(Level.SEVERE, "Unable to determine log file name.", ex);
                }
            }
        }
        if (logFileName == null) {
            logFileName = "your home directory"; // just be sure it's not null
            logger.warning("Unable to identify log file name.");
        }
    }
    return logFileName;
}

The reflection hack works fine in both Java 8 & 9, but in Java 9, it generates the following warning which I'd prefer to fix rather than ignore with the --illegal-access=permit flag.

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.foo.MyApp (file:/C:/Users/me/Documents/foo/build/classes/java/main/) to field java.util.logging.FileHandler.files
WARNING: Please consider reporting this to the maintainers of org.foo.MyApp
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Any ideas? Thanks.

2条回答
唯我独甜
2楼-- · 2019-08-23 04:51

If a linux-specific solution is good enough you can try resolving the pseudo-symlinks in /proc/self/fd/, one of them should be the currently open logfile, matching the logging file pattern.

查看更多
霸刀☆藐视天下
3楼-- · 2019-08-23 05:11

There are several ways to do this:

  1. File a change request with the JDK to allow access to the field (at least make it protected so you can read it in a subclass).
  2. Parse the properties file used to configure the appender. You will have to copy some of the logic out of the Java 9 code but chances are that this code won't change for a long time (backwards compatibility).
  3. Copy a lot of code out of the logging API so you can write your own FileHandler which allows access to the field. While at it, you could also add code to iterate over all appenders.
  4. Use a different logging framework.
查看更多
登录 后发表回答