Missing slash on Java 9’s LogManager.getLogger() / Logger.getHandlers() seems to cause an exception

纵然是瞬间 提交于 2020-01-23 03:20:07

问题


I am seeing a problem with an Applet on Windows, running Java 9, when I am trying to create a log file C:\Users\cardal\ApplicationLog.html. The code works fine on Java 8.

The code does LogManager.readConfiguration () and LogManager.getLogger(). Then Logger.getHandlers() hits an exception. It looks like the first slash is getting removed by mistake:

Can't load log handler "java.util.logging.FileHandler"
java.nio.file.NoSuchFileException: C:Users\cardal\ApplicationLog.html.lck
java.nio.file.NoSuchFileException: C:Users\cardal\ApplicationLog.html.lck
at java.base/sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at java.base/sun.nio.fs.WindowsFileSystemProvider.newFileChannel(Unknown Source)
at java.base/java.nio.channels.FileChannel.open(Unknown Source)
at java.base/java.nio.channels.FileChannel.open(Unknown Source)
at java.logging/java.util.logging.FileHandler.openFiles(Unknown Source)
at java.logging/java.util.logging.FileHandler.<init>(Unknown Source)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.base/java.lang.Class.newInstance(Unknown Source)
at java.logging/java.util.logging.LogManager.createLoggerHandlers(Unknown Source)
at java.logging/java.util.logging.LogManager.access$1300(Unknown Source)
at java.logging/java.util.logging.LogManager$4.run(Unknown Source)
at java.logging/java.util.logging.LogManager$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.logging/java.util.logging.LogManager.loadLoggerHandlers(Unknown Source)
at java.logging/java.util.logging.LogManager.initializeGlobalHandlers(Unknown Source)
at java.logging/java.util.logging.LogManager.access$1800(Unknown Source)
at java.logging/java.util.logging.LogManager$RootLogger.accessCheckedHandlers(Unknown Source)
at java.logging/java.util.logging.Logger.getHandlers(Unknown Source)
at appletExample.TestAppletLAC._getAllSpecificHandlers(TestAppletLAC.java:238)
at appletExample.TestAppletLAC.loadConfig(TestAppletLAC.java:116)
at appletExample.TestAppletLAC.reloadCoreLoggerProperties(TestAppletLAC.java:184)
at appletExample.TestAppletLAC.paint(TestAppletLAC.java:283)
at java.desktop/sun.awt.RepaintArea.paintComponent(Unknown Source)
at java.desktop/sun.awt.RepaintArea.paint(Unknown Source)
at java.desktop/sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.EventQueue.access$500(Unknown Source)
at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

Is the code doing something wrong?

The Java console output verifies that the first slash exists in strLogConfig:

LAC: reloadCoreLoggerProperties strLogConfig is 
handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler
.level=WARNING
java.util.logging.ConsoleHandler.level=WARNING
java.util.logging.FileHandler.level=WARNING
java.util.logging.FileHandler.pattern=C:/Users/cardal/ApplicationLog.html
java.util.logging.FileHandler.formatter=com.emc.navisphere.gui.core
.utilities.logger.HTMLFormatter
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

The Java console output also verifies that the first slash exists in the stream before and after calling readConfiguration:

LAC: reloadCoreLoggerProperties myBytes[218] is 58  “:”
LAC: reloadCoreLoggerProperties myBytes[219] is 47  “/”
LAC: reloadCoreLoggerProperties myBytes[220] is 85  “U”

Below is the code (I removed some exception coding to simplify the code). I can post the entire Java console log output if needed.

Thanks!

package appletExample;

import java.applet.Applet;
import java.awt.*;

import java.util.Properties;
import java.util.logging.ConsoleHandler;
import java.util.logging.LogManager;
import java.text.MessageFormat;
import java.util.Enumeration;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import java.util.logging.Logger;
import java.util.logging.FileHandler;
import java.util.logging.Handler;

public class TestAppletLAC extends Applet  {

  // try double backward slash, for now.
  private static String NEW_LOG_FILE_DIR = "C:\\Users\\cardal\\";

  public static String getDefaultOutputFileName() {
    return NEW_LOG_FILE_DIR + "ApplicationLog.html";
  }

  /** Default Logging Config */
  private static final String DEFAULT_CONFIG     = "handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler\n"
      + ".level={0}\n"
      + "java.util.logging.ConsoleHandler.level={0}\n"
      + "java.util.logging.FileHandler.level={0}\n"
      + "java.util.logging.FileHandler.pattern={1}\n"
          + "java.util.logging.FileHandler.formatter=com.emc.navisphere.gui.core.utilities    .logger.HTMLFormatter\n"
          + "java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter";
private final static String seperator = System.getProperty    
("file.separator");

/** a LogManager */
private LogManager _manager = LogManager.getLogManager();

public static String getDefaultLogFile(String strLogFile) {
String strReturn = "";
// Logger wants the "/" not "\"
strLogFile = strLogFile.replace("\\", "/");

strReturn = MessageFormat.format(DEFAULT_CONFIG, new Object[] {
      "WARNING", strLogFile });

  // lac debug
  System.out.println("LAC: getDefaultLogFile strReturn is " + strReturn);
return strReturn;
  }

/**
  * Loads config file using an InputStream 
   * 
   * @param stream
   *          - stream
   */
  public synchronized boolean loadConfig(InputStream stream) {
boolean bReturn = false;
try {
  if (stream != null) 
  {

   // lac debug
   System.out.println("LAC: loadConfig: printing out InputStream stream.  Look for colon (58) then slash (47)");

   // LAC
   for(int y = 0 ; y < 1; y++) 
   {
    int  c;
     while(( c = stream.read())!= -1) 
     {
        System.out.println(c);
     }
     stream.reset(); 
   }

   // LAC: debug
   System.out.println("lac: loadConfig: _manager.readConfiguration(stream) ");
    /**
     * first configure loggers by the LogManager as getAllSpecificHandlers
     * may call logmanager
     */
    _manager.readConfiguration(stream);
    stream.reset();

    // lac debug
   System.out.println("LAC: loadConfig: AFTER READCONFIGURATION: printing out InputStream stream.  Look for colon (58) then slash (47)");

   // LAC
   for(int y = 0 ; y < 1; y++) 
   {
    int  c;
     while(( c = stream.read())!= -1) 
     {
        System.out.println(c);
     }
     stream.reset(); 
   }

   // LAC: debug
   System.out.println("lac: loadConfig: Calling _getAllSpecificHandlers(stream)");

   /** add all specific handlers to loggers as neccessary */
   _getAllSpecificHandlers(stream);
   bReturn = true;
  }
} catch (Exception e) {
}
return bReturn;
}

public void reloadCoreLoggerProperties() {
try 
{
   InputStream defaultNaviConfig = null;

   // lac debug
   System.out.println("LAC: reloadCoreLoggerProperties getDefaultOutputFileName is " + getDefaultOutputFileName());

   // lac debug
   System.out.println("LAC: reloadCoreLoggerProperties seperator from system.getproperty of file.separator is " + seperator);
   // lac debug
   System.out.println("LAC: reloadCoreLoggerProperties NEW_LOG_FILE_DIR is " + NEW_LOG_FILE_DIR);

   String strLogConfig = getDefaultLogFile(getDefaultOutputFileName());

   // lac debug
   System.out.println("LAC: reloadCoreLoggerProperties strLogConfig is " + strLogConfig);

   // lac debug
   byte[] myBytes = strLogConfig.getBytes("UTF-8");
   System.out.println("LAC: reloadCoreLoggerProperties myBytes at 209 -> 217 is 112,97,116,116,101,114,110,61,67 (pattern=C)");
   System.out.println("LAC: reloadCoreLoggerProperties myBytes at 218 is 58 (colon)");
   System.out.println("LAC: reloadCoreLoggerProperties myBytes at 219 should be 47 (forward slash)");
   System.out.println("LAC: reloadCoreLoggerProperties myBytes at 220 should be 85 (U)");
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[208] is " + myBytes[208]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[209] is " + myBytes[209]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[210] is " + myBytes[210]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[211] is " + myBytes[211]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[212] is " + myBytes[212]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[213] is " + myBytes[213]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[214] is " + myBytes[214]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[215] is " + myBytes[215]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[216] is " + myBytes[216]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[217] is " + myBytes[217]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[218] is " + myBytes[218]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[219] is " + myBytes[219]);
   System.out.println("LAC: reloadCoreLoggerProperties myBytes[220] is " + myBytes[220]);

   // lac debug
   System.out.println("LAC: reloadCoreLoggerProperties about to do new ByteArrayInputStream(strLogConfig)");
        defaultNaviConfig = new ByteArrayInputStream(strLogConfig
            .getBytes("UTF-8"));

   // lac debug
   System.out.println("LAC: reloadCoreLoggerProperties printing out defaultNaviConfig.  Look for colon (58) then slash (47)");

  // LAC
  for(int y = 0 ; y < 1; y++) 
  {
    int  c;
     while(( c = defaultNaviConfig.read())!= -1) {
        System.out.println(c);
     }
     defaultNaviConfig.reset(); 
  }

  // lac debug
  System.out.println("LAC: about to call loadConfig with defaultNaviConfig");

  // Load the logging configuration
  loadConfig(defaultNaviConfig);
  defaultNaviConfig.close();
} catch (Exception e) 
{
}
}

  private void _getAllSpecificHandlers(InputStream stream) {
Properties properties = new Properties();
try {
  // LAC: debug
  System.out.println("lac: TOP OF _getAllSpecificHandlers; properties.load(stream) to get the properties.");

  properties.load(stream);
} catch (IOException ex) {
}

// LAC: debug
System.out.println("lac: Looping through the properties.");
Enumeration<?> propkeys = properties.propertyNames();
while (propkeys.hasMoreElements()) 
{
  String loggerHasHandler = (String) propkeys.nextElement();

  // LAC: Print the properties and values.
   System.out.println("lac: key:value " + loggerHasHandler
   +":"+_getProperty(loggerHasHandler));

  if (loggerHasHandler.contains(".SpecificFileHandler.formatter")) 
  {
    int end = loggerHasHandler.indexOf(".SpecificFileHandler.formatter");
    String loggerName = loggerHasHandler.substring(0, end);
  }
  else if (loggerHasHandler
      .equalsIgnoreCase("java.util.logging.FileHandler.formatter")
      || loggerHasHandler
          .equalsIgnoreCase("java.util.logging.ConsoleHandler.formatter")) 
  {
    /** get value and see if it is our HTMLFormatter */
    String formatterValue = _getProperty(loggerHasHandler);

    // LAC: debug
    System.out.println("lac: formatterValue is " + formatterValue);

    if (formatterValue.contains("HTMLFormatter"))
    {
      // LAC: debug
      System.out.println("lac: Found HTMLFormatter; ABOUT TO _manager.getLogger()");

      Logger rootLogger = _manager.getLogger("");

      // LAC: debug
      System.out.println("lac: ABOUT TO DO rootLogger.getHandlers() AND GET EXCEPTION");

      Handler[] h = rootLogger.getHandlers();

      // LAC: debug
      System.out.println("lac: AFTER THE EXCEPTION, BEFORE THE LOOP");

      for (int i = 0; i < h.length; i++) 
      {
        if ((h[i] instanceof FileHandler && loggerHasHandler
            .contains("FileHandler"))
            || (h[i] instanceof ConsoleHandler && loggerHasHandler
                .contains("ConsoleHandler"))) 
        {
          Handler aHandler = h[i];
          rootLogger.removeHandler(aHandler);
          rootLogger.addHandler(aHandler);
        }
      }
    }
  }
}
}

  /**
   * This will return the corresponding values of the key as defined in a config
  * file.
  * 
  * @param key
  *          - key to look for the properties
  * @return value from the key
  */
     private String _getProperty(String key) {
String value = _manager.getProperty(key);
if (null != value) {
  return value.trim();
}
return _manager.getProperty(key);
}

public void paint(Graphics g) {
    // Draw a rectangle width=250, height=100
    g.drawRect(0, 0, 500, 100);
    // Set the color to blue
    g.setColor(Color.blue);
    g.drawString("Testing log on java versions",10,50);

   reloadCoreLoggerProperties();
}

public void init() 
{
}
}

回答1:


This has already been reported as bug under JDK-8189953: FileHandler constructor throws NoSuchFileException with absolute path.

From the bug report it appears to be an issue with absolute paths. Since your are locating the home directory, change the file pattern to use %h:

java.util.logging.FileHandler.pattern=%h\ApplicationLog.html

Otherwise, per the FileHandler documentation the forward slash is replaced at runtime. So you can try to use back slash instead.

java.util.logging.FileHandler.pattern=C:\Users\cardal\ApplicationLog.html

When the bug report is fixed, you should be able to simply upgrade to a newer version of Java 9.



来源:https://stackoverflow.com/questions/46980752/missing-slash-on-java-9-s-logmanager-getlogger-logger-gethandlers-seems-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!